本文基於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時會執行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時重新賦值(爲啥要重新賦值????暫時沒有分析)。