- 本篇笔记主要是针对ViewModel的源码进行分析
- 深入了解架构组件之ViewModel
一.简介
- 官网
- ViewModel类是被设计用来以可感知生命周期的方式存储和管理 UI 相关数据,ViewModel中数据会一直存活即使 activity configuration发生变化,比如横竖屏切换的时候。
- 优点
- 数据持久化
- 异步回调问题,不会造成内存泄漏
- 在Mvvm架构中隔离Model层与View层
- 可实现Fragments间共享数据
二.基本使用
- ViewModel环境:implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
- 基本使用方面是略写,使用方面的细节大家可以参考其它资料,本篇笔记以源码分析为主。
2.1.自定义ViewModel的实现类
public class MyViewModel extends ViewModel {
private MutableLiveData<String> number;
private MutableLiveData<User> user;
public MutableLiveData<String> getNumber(){
if(number == null){
number = new MutableLiveData<>();
number.setValue("");
}
return number;
}
public MutableLiveData<User> getUser(){
if(user == null){
user = new MutableLiveData<>();
}
return user;
}
public void getUserFromNet(){
//获取数据
}
}
2.2.在MainActivity中使用
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
//ViewModel的创建不能直接去new
//当我们执行这句代码的时候,会去ViewModelStore获取MyViewModel对象,如果没有就创建一个
//问题1:为什么通过一下方式进行创建,得到的ViewModel会是同一个
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
textView.setText( myViewModel.getNumber().getValue()+"");
}
public void changeData(View view) {
myViewModel.getNumber().setValue(myViewModel.getNumber().getValue()+1);
}
@Override
protected void onDestroy() {
super.onDestroy();
}
public void changeData2(View view) {
myViewModel.getNumber().setValue(myViewModel.getNumber().getValue()+1);
}
}
三.源码分析
- 我们从ViewModel的创建,作为源码分析的入口
3.1.分析ViewModelProvider的构造方法
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
//4.将ComponentActivity中的成员变量mViewModelStore赋值给ViewModelProvider中的成员变量mViewModelStore
//1.继续调用其它构造方法
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
//2.将store(activity)赋值给mViewModelStore,在3.2中分析ViewModelStore
mViewModelStore = store;
}
3.2.ViewModelStore
public class ViewModelStore {
//保存ViewModel的map
private final HashMap<String, ViewModel> mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
ViewModel oldViewModel = mMap.put(key, viewModel);
if (oldViewModel != null) {
oldViewModel.onCleared();
}
}
final ViewModel get(String key) {
return mMap.get(key);
}
Set<String> keys() {
return new HashSet<>(mMap.keySet());
}
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
- 当activity的生命周期结束了,ViewModelStore依然存在。在2.2中,当ViewModle被创建出来了,就会将ViewModel放到ViewModelStore中。当再次去get的时候,会检查ViewModelStore中的map是否存在,存在直接获取,不存在才创建。下面分析一下get方法源码
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
//拿到包名+类名
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
//3.现根据key去获取,获取到了就直接返回,未获取到才创建
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass); //4.重新创建
} else {
viewModel = (mFactory).create(modelClass);
}
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
-
MainAvtivity的生命周期其实和ViewModel的生命周期是没有关联的。
-
问题2:ViewModelStore是怎么实现不被销毁的
-
注意:sdk 30跟28存在着很大的区别,ViewModelStore的管理是存在着很大的差异,28是通过fragment来管理的,现在是把ViewModelStore写成了一个共有数据;
-
此时我们再回到步骤1,分析owner.getViewModelStore();
-
问题3:activity关闭了,ViewModel依然存在,其原因是什么?分析步骤4
3.3.(mFactory).create(modelClass)
public interface Factory {
@NonNull
<T extends ViewModel> T create(@NonNull Class<T> modelClass);
}
//找实现类-AbstractSavedStateViewModelFactory
public final <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
//临时保存数据的(内存中),当后台进程关闭,数据也能得到保留
//ViewModel是存在SavedStateHandleController中的(重点-需要记忆)
SavedStateHandleController controller = SavedStateHandleController.create(
mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
T viewmodel = create(key, modelClass, controller.getHandle());
viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
return viewmodel;
}
- 问题2和问题3其实是同一类问题,3.3中的注释有解释;
3.4.ViewModel销毁的时机
- 在activity的父类ComponentActivity中的构造方法中,利用了Lifecycle,当activity的生命周期方法触发,并且!isChangingConfigurations()为true,ViewModel就会被销毁;
public ComponentActivity() {
//...
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
//...
}
3.5.总结
- 把上面提及到的三个问题弄清楚了,ViewModle源码相关也差不多了。
评论区