本文基于ViewModel 2.1.0
先来一张ViewModel生命周期图
原文
AndroidX设计架构MVVM之ViewModel创建流程原理分析
AndroidX设计架构MVVM之ViewModel生命周期分析
AndroidX设计架构MVVM之LiveDatal生命周期及数据监听分析
AndroidX设计架构MVVM之DataBinding搭配LiveData的分析
AndroidX设计架构MVVM之DataBinding+ViewModel+LiveData
从google官网获取的ViewModel生命周期图,图中显示activity在横竖屏旋转重建时ViewModel一直存在内存中
ViewModel创建流程原理分析的总结中提到一个activity中只有一个ViewModelStore,ViewModelStore中保存此activity中所有ViewModel。
那么根据ViewModel的生命周期图来看看,当activity在生命周期onDestroy中是如何处理ViewModel的。
@Override
protected void onDestroy() {
super.onDestroy();
//注意点1
if (mViewModelStore != null && !isChangingConfigurations()) {
//注意点2
mViewModelStore.clear();
}
mFragments.dispatchDestroy();
}
注意点1:关键点isChangingConfigurations(),从名字上就知道是判断当前是否为切换横竖屏。
public boolean isChangingConfigurations() {
return mChangingConfigurations;
}
/** true if the activity is being destroyed in order to recreate it with a new configuration */
/*package*/ boolean mChangingConfigurations = false;
mChangingConfigurations 属性的注释:当为true时,表示activity使用新的configuration 进行重建。这部分放到最下面分析,现在只需要知道mChangingConfigurations =ture,activity重建时,不执行(注意点2) mViewModelStore.clear();
那么问题来了,old activity都销毁了,它包含的ViewModelStore怎么会没有回收呢?
在activity旋转重建,销毁old activity前,对当前的ViewModelStore进行了保存,然后在新生成的activity中进行了恢复。
先看保存的地方,old activity执行onDestroy时,在真正销毁之前ActivityThread会调用activity的retainNonConfigurationInstances——>onRetainNonConfigurationInstance,保存当前的mViewModelStore。
public final Object onRetainNonConfigurationInstance() {
。。。。。。
//保存mViewModelStore
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = mViewModelStore;
nci.fragments = fragments;
return nci;
}
再看恢复的地方,主要有两个地方activity的onCreate中和getViewModelStore()()可以参考ViewModel创建流程原理分析
//恢复地方1
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
//判断最后保存的非配置实例不为空,且保存的viewModelStore 不为空
//而当前activity的mViewModelStore 为空时进行赋值
if (nc != null && nc.viewModelStore != null && mViewModelStore == null) {
mViewModelStore = nc.viewModelStore;
}
。。。。。。。
}
//恢复地方2
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) {
//由于在oncreate中恢复过,所以为重新恢复
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
return mViewModelStore;
}
###############################################################################
下面分析mChangingConfigurations 在什么地方设置为true。不关心的话这部分可以不看哈
但activity重建时会调用recreate(),注释说明会销毁现有的activity实例,重建一个先的实例
/**
* Cause this Activity to be recreated with a new instance. This results
* in essentially the same flow as when the Activity is created due to
* a configuration change -- the current instance will go through its
* lifecycle to {@link #onDestroy} and a new instance then created after it.
*/
public void recreate() {
if (mParent != null) {
throw new IllegalStateException("Can only be called on top-level activity");
}
if (Looper.myLooper() != mMainThread.getLooper()) {
throw new IllegalStateException("Must be called from main thread");
}
//注意点3
mMainThread.scheduleRelaunchActivity(mToken);
}
注意点3:通过ActivityThread发送RELAUNCH_ACTIVITY 的message。
void scheduleRelaunchActivity(IBinder token) {
sendMessage(H.RELAUNCH_ACTIVITY, token);
}
//handler中接收到消息
case RELAUNCH_ACTIVITY:
//注意点4
handleRelaunchActivityLocally((IBinder) msg.obj);
break;
}
注意点4:这部分简单说吧(对本文没特别大的意义)。handleRelaunchActivityLocally()的一部分工作就是合并新的和旧的配置到新创建的activity中,最终会走到activityThread的handleRelaunchActivity().并修改mChangingConfigurations 为true
public void handleRelaunchActivity(ActivityClientRecord tmp,
PendingTransactionActions pendingActions) {
....................
//在执行重新创建的中修改为true
r.activity.mChangingConfigurations = true;
....................
总结:如果activity的生命周期是因为发生旋转造成的,那么在old activity销毁的时候,保存了ViewModelStore对象,并将old activity 的mChangingConfigurations 设置为true,即不清空ViewModelStore中保存的ViewModel。当新new activity执行oncreate时,赋值给new activity的mViewModelStore,并在获取new activity的ViewModelStore时重新确认并赋值。