AndroidX设计架构MVVM之ViewModel生命周期分析

本文基于ViewModel 2.1.0
先来一张ViewModel生命周期图

原文
AndroidX设计架构MVVM之ViewModel创建流程原理分析
AndroidX设计架构MVVM之ViewModel生命周期分析
AndroidX设计架构MVVM之LiveDatal生命周期及数据监听分析
AndroidX设计架构MVVM之DataBinding搭配LiveData的分析
AndroidX设计架构MVVM之DataBinding+ViewModel+LiveData
AndroidX设计架构MVVM之ViewModel生命周期分析_第1张图片
从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时重新确认并赋值。

你可能感兴趣的:(Android)