版本
'androidx.appcompat:appcompat:1.2.0'
想要ViewModel不随着宿主重建而销毁,那就要保证ViewModelStore不随着宿主重建而销毁。那么ViewModelStore又是在什么时机被保存起来的呢?
答: 通过ComponentActivity中的onRetainNonConfigurationInstance和getLastNonConfigurationInstance方法保存ViewModelStore对象
1.首先看一下ComponentActivity中获取ViewModelStore的getViewModelStore()方法
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,如果不为空再获取viewModelStore
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
//如果未获取到,则创建ViewModelStore对象
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
NonConfigurationInstances
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
2.接下来看ComponentActivity中onRetainNonConfigurationInstance()方法如何保存viewModelStore
public final Object onRetainNonConfigurationInstance() {
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// 如果NonConfigurationInstance保存了viewModelStore,把它取出来
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
// 把viewModelStore放到NonConfigurationInstances中并返回,这样当页面被重建而销毁时ViewModelStore就被保存起来了
nci.viewModelStore = viewModelStore;
return nci;
}
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
3.那么onRetainNonConfigurationInstance()方法又是何时被调用的呢?
在Activity启动流程中,当ActivityThread执行performDestroyActivity这个方法时,会调用Activity的retainNonConfigurationInstances()方法获取到保存的数据并保存到ActivityClientRecord中。
//Activity中的retainNonConfigurationInstances()方法
NonConfigurationInstances retainNonConfigurationInstances() {
//ComponentActivity中的onRetainNonConfigurationInstance()方法
Object activity = onRetainNonConfigurationInstance();
···
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
···
return nci;
}
ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing, int configChanges, boolean getNonConfigInstance, String reason) {
...
//保存retainNonConfigurationInstances中的数据到ActivityClientRecord中
ActivityClientRecord r = mActivities.get(token);
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
...
return r;
当页面重建完成,ActivityThread执行了performLaunchActivity方法时,会调用Activity的attach方法,便会把刚刚存储的数据,传递进去。
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//传递之前储存的数据
activity.attach(......, r.lastNonConfigurationInstances,.....);
}