一、前言
之前我们已经介绍了ViewModel的意义和使用方式。我们知道,在一个Activity创建ViewModel对象的时候,当由于系统配置变化导致Activity销毁重建的时候,ViewModel对象并不会被有任何影响,由此可知在ViewModel中存储的数据,也不会发生变化。这对于我们开发者来说是很方便的。
我们知道Activity的onSaveInstanceState和onRestoreInstanceState也可以做到这一点,但是我们知道onSaveInstanceState和onRestoreInstanceState是通过把数据序列化到内存,再从内存中反序列化出来。通常是针对一些可以序列化和反序列化的小量数据,如果是大量的数据,或者没有序列化的,则不行了。
了解了ViewModel的强大的功能之后,我们先用一张图来描述ViewModel的生命周期的变化:
从图中我们可以看到,只有Activity真正的销毁的时候,ViewModel才会被清除掉,对应图中的onCleared方法。
二、源码解析
下面我们来分析ViewModel的源码。我们先看下ViewModel对象的创建方式:
viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
代码很简单,首先调用ViewModelProviders的of方法创建ViewModelProvider对象。其实从类的命名上看就很容易理解,ViewModelProviders和ViewModelProvider只差一个s,ViewModelProviders是一个集合,ViewModelProvider是集合中的一个对象,of(this)则是通过传入当前Activitiy的实例作为key,获取ViewModelProviders中ViewModelProvider对象。是不是这个意思呢?我们继续分析:
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment) {
return of(fragment, null);
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity) {
return of(activity, null);
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {
Application application = checkApplication(checkActivity(fragment));
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(ViewModelStores.of(fragment), factory);
}
@NonNull
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application = checkApplication(activity);
if (factory == null) {
factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}
return new ViewModelProvider(ViewModelStores.of(activity), factory);
}
我们看到of方法中有四个重载的方法,她们的区别就是传入的this是Activity还是Fragment,还有就是,是否有Factory 对象。如果没有Factory对象,则创建默认的Factory。然后通过以下方式返回ViewModelProvider 对象
return new ViewModelProvider(ViewModelStores.of(fragment), factory);
我们看下ViewModelProvider的构造函数:
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {
mFactory = factory;
this.mViewModelStore = store;
}
ViewModelStore 和Factory 对象顾名思义ViewModelStore 是用来存储ViewModel的Factory 是用来创建ViewModel的。通过ViewModelStores.of(fragment)创建获取ViewModelStore实例,接着我们看下ViewModelStores.of(fragment)的实现
@NonNull
@MainThread
public static ViewModelStore of(@NonNull Fragment fragment) {
if (fragment instanceof ViewModelStoreOwner) {
return ((ViewModelStoreOwner) fragment).getViewModelStore();
}
return holderFragmentFor(fragment).getViewModelStore();
}
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public static HolderFragment holderFragmentFor(Fragment fragment) {
return sHolderFragmentManager.holderFragmentFor(fragment);
}
HolderFragment holderFragmentFor(Fragment parentFragment) {
FragmentManager fm = parentFragment.getChildFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedFragmentHolders.get(parentFragment);
if (holder != null) {
return holder;
}
parentFragment.getFragmentManager()
.registerFragmentLifecycleCallbacks(mParentDestroyedCallback, false);
holder = createHolderFragment(fm);
mNotCommittedFragmentHolders.put(parentFragment, holder);
return holder;
}
HolderFragment holderFragmentFor(FragmentActivity activity) {
FragmentManager fm = activity.getSupportFragmentManager();
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedActivityHolders.get(activity);
if (holder != null) {
return holder;
}
if (!mActivityCallbacksIsAdded) {
mActivityCallbacksIsAdded = true;
activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
}
holder = createHolderFragment(fm);
mNotCommittedActivityHolders.put(activity, holder);
return holder;
}
我们看到获取ViewModelStore实例最终调用了holderFragmentFor方法获取HolderFragment 实例holder ,而HolderFragment 继承了ViewModelStoreOwner。在holderFragmentFor方法中首先根据activity作为key,判断holder 是否存在。如果存在里,就直接返回holder。
HolderFragment holder = findHolderFragment(fm);
if (holder != null) {
return holder;
}
holder = mNotCommittedActivityHolders.get(activity);
if (holder != null) {
return holder;
}
如果不存在则创建新的holder返回,并把holde存到mNotCommittedActivityHolders这个Map中,以Activity作为key。
if (!mActivityCallbacksIsAdded) {
mActivityCallbacksIsAdded = true;
activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks);
}
holder = createHolderFragment(fm);
mNotCommittedActivityHolders.put(activity, holder);
return holder;
这样一来我们可以知道,只要HolderFragment 没有被销毁,mNotCommittedActivityHolders这个Map就会存在,那么存放在Map中的ViewModelStoreOwner holder就存在。
return holderFragmentFor(fragment).getViewModelStore();
然后通过getViewModelStore()方法可以得到ViewModelStore对象。
接着我们看下get方法
viewModel = ViewModelProviders.of(this).get(MainViewModel.class);
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
//noinspection unchecked
return (T) viewModel;
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
//noinspection unchecked
return (T) viewModel;
}
我们很容易知道,首先从Map中根据key获取ViewModel 对象
ViewModel viewModel = mViewModelStore.get(key);
如果viewModel 不为空,则返回,否则创建一个ViewModel对象,存放在Map中。
ViewModel oldViewModel = mMap.put(key, viewModel);
并且我们知道存放ViewModel的Key和Activity或者Fragment是对应起来的。所以说当Activity重建的时候,只要mViewModelStore对象还是原来的对象,那么ViewModel对象就不会变,而且我们在上面分析知道mViewModelStore又存放到了HolderFragment中,也是存放到了Map中,所以只要HolderFragment没有被销毁,mViewModelStore就不会被销毁。mViewModelStore没有被销毁,ViewModel就没有被销毁。ViewModel没有被销毁,ViewModel里面的数据就没有被销毁。因此得出了我们的结论。在Activity销毁重建的时候,ViewModel里的数据是不会丢失的。
三、小结
我们对ViewModel的源码做一个小结:
1、创建HolderFragment,并在HolderFragment中初始化Map<Activity, HolderFragment> mNotCommittedActivityHolders 用于存放 HolderFragment holder。
2、从HolderFragment 获取ViewModelStore mViewModelStore
3、ViewModelStore 用于存放ViewModel对象,创建ViewModelProvider实例,传入ViewModelStore 对象,对ViewModelProvider中的ViewModelStore进行初始化。
4、通过 mViewModelStore.put(key, viewModel);获取ViewModel实例。
其实ViewModel最核心的部分就是HolderFragment 中存放了ViewModelStore 。因为Activity在销毁重建的时候HolderFragment 并不收到影响,所以ViewModelStore 不会丢失。从而下面的一系列得到ViewModel对象不会销毁。