一:获取view model的代码
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = mViewModelStore.get(key);//从一个hash map中用key取view model,key是view model的类名。
if (modelClass.isInstance(viewModel)) {//如果还没有view model实例,即上一步得到null, 那么就不会进去,如果进入了,就会返回view mdoel了
if (mFactory instanceof OnRequeryFactory) {
((OnRequeryFactory) mFactory).onRequery(viewModel);
}
return (T) viewModel; //返回view model
} else {
//noinspection StatementWithEmptyBody
if (viewModel != null) {
// TODO: log a warning.
}
}
if (mFactory instanceof KeyedFactory) {
viewModel = ((KeyedFactory) mFactory).create(key, modelClass);//创建view model
} else {
viewModel = mFactory.create(modelClass);//创建view model
}
mViewModelStore.put(key, viewModel);//往map里面插入这个view model
return (T) viewModel;
}
activity实现了view model store owner,拥有view model store,view model store则拥有一个map存放view model。
但是当配置更改时,view model store实例如何才能保证是旧的那个呢?
二:如何不改变view model store
首先来看看activity如何获取view model store
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}//忽略
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();//这个重点
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
因为activity创建时view model store都是null,当我们第一次取时,会看看nc,如果nc不为null,代表nc存有以前的view model,就取出来就行了,没有就创建。
所以关键是,这个nc是什么,它是如何保存我们之前的viewmodel的,为森马它不为空,就存有旧 viewmodel呢?
搞明白这个nc,就知道view mdoel store是如何不变的了。
三:搞明白NonCon.....Instances如何存
在上一段代码中,ComponenetActivity.java的getViewModelStore方法会调用Activity.java的getLastNCI方法,getLastNCI方法会返回Activity.java内部的一个NCI对象
static final class NonConfigurationInstances {
Object activity;
。。。。。
}
那为什么这个对象会存有我们的viewmdoelstore实例呢?
原因就是:
当Activity.java销毁的时候,会保存Activity.NCI实例:
Activity,java
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();
......
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
return nci;
}
ComponentActivity.java
public final Object onRetainNonConfigurationInstance() {
ViewModelStore viewModelStore = mViewModelStore;
......
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.viewModelStore = viewModelStore;
return nci;
}
activity销毁的时候,系统会调用retainXXXX,然后调用 onRetainXXXX,把view model store存进去了,把ComponentActivity.java的NCI对象存到Activity.java的NCI对象的一个叫做“activity”的变量里面,这个变量名十分误导人,叫其他不好吗?叫store也好啊!!
四:搞明白NonCon.....Instances如何恢复
系统调用Activity.java的attach方法
Activity.java
final void attach( NonConfigurationInstances lastNonConfigurationInstances){
...
mLastNonConfigurationInstances = lastNonConfigurationInstances
...
}
这样呢,在第二部分 ComponentActivity.java获取viewmdoelstore的方法里就可以获取到这个NCI了。
整体流程如下
参考:https://blog.mindorks.com/android-viewmodels-under-the-hood