学习过ViewModel的都知道,ViewModel主要对数据进行存储维护,当在异常情况下(横竖屏)Activity被销毁的时候恢复数据。
在Android中想要维护异常销毁Activity都是通过以上三种方法,因为方法一需要序列化的缘故,大数据的数据恢复我们一般用后面两种方法,了解了这些简单的知识点后,接下来我们来看看ViewModel的源码。
让我们先来看看获取ViewModel的入口代码:
1.FragmentActivity
final ProjectViewModel viewModel = ViewModelProviders.of(this, viewModelFactory)
.get(ProjectViewModel.class);
2.ViewModelProviders
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
...
return new ViewModelProvider(activity.getViewModelStore(), factory);
}
代码块1使用ViewModelProviders.of静态方法创建ViewModelProvider的对象,这里我们先不考虑activity.getViewModelStore()的逻辑,继续看下去,然后调用其ViewModelProvider.get方法:
public T get(@NonNull Class modelClass) {
String canonicalName = modelClass.getCanonicalName();
...
return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}
public T get(@NonNull String key, @NonNull Class modelClass) {
1.从ViewModelStore获取ViewModel
ViewModel viewModel = mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
2.取出的对象不为null 并且 为 传入的Class直接返回
return (T) viewModel;
} else {
..
}
3.在工厂类中获取到新的ViewModel对象,并保存在ViewModelStor中
viewModel = mFactory.create(modelClass);
mViewModelStore.put(key, viewModel);
return (T) viewModel;
}
以上获取ViewModel的流程我们可以总结为:
到这里我们可以尝试着看看ViewModelStore是一个什么类?
public class ViewModelStore {
private final HashMap mMap = new HashMap<>();
final void put(String key, ViewModel viewModel) {
...
}
final ViewModel get(String key) {
...
}
public final void clear() {
...
}
}
从类名我们就可以看出来,这个类的功能主要是:为了存储ViewModel,其内部核心就是使用HashMap对ViewModel进行管理,其对象的获取办法我们回到上面的 ViewModelProviders.of() 查看:activity.getViewModelStore()
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
...
}
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
从上面的代码片段我们可以看出大致的逻辑流程为:
以上就是获取ViewModelStore的流程,既然有恢复数据的流程,那么就要看一下保存数据的流程,保存数据的按照原理是在FragmentActivity
.onRetainNonConfigurationInstance()中:
public final Object onRetainNonConfigurationInstance() {
...
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = mViewModelStore;
nci.fragments = fragments;
return nci;
}
从代码中可知,当出现异常情况销毁时onRetainNonConfigurationInstance()方法会被调用保存数据对象,然后在FragmentActivity.getLastNonConfigurationInstance被调用的时候进行恢复数据。
最终当Activity进行销毁时会调用FragmentActivity.onDestroy()方法,假如当前不是屏幕滚动导致的销毁,那么ViewModelStore会被清理资源:
protected void onDestroy() {
super.onDestroy();
if (mViewModelStore != null && !isChangingConfigurations()) {
mViewModelStore.clear();
}
}
Fragment的原理稍微简单点,其实就是直接创建ViewModelStore对象进行维护ViewModel,利用Fragment.setRetainInstance()的特性让在Fragment的ViewModelStore对象在Activity横竖屏翻滚的时候不进行回收对象的处理
public interface Factory {
@NonNull
T create(@NonNull Class modelClass);
}
Factory类是一个对象,定义了创建ViewModel的协议接口,ViewModel框架提供了两个实现类NewInstanceFactory和AndroidViewModelFactory,使用的是Class反射创建对象。