美文网首页mvxjetpack
深入理解AAC架构 - ViewModel 使用以及整体机制源码

深入理解AAC架构 - ViewModel 使用以及整体机制源码

作者: 七零八落问号 | 来源:发表于2020-02-21 16:30 被阅读0次

    本文主要内容:

    1. 作用介绍
    2. 核心类介绍
    3. 基本使用
    4. 源码分析
      -- 横竖屏切换恢复
      -- 后台销毁恢复

    ViewModel的主要工作:

    本身主要是一个数据维护工具
    将数据维护的工作从Activity上剥离,提供一个储存数据环境,自身机制可以解决开发中,数据受Activity生命周期影响产生数据丢失的问题 (主要为横竖屏切换以及在后台被销毁)。
    通常结合LiveData使用。

    官方介绍上的生命周期图 (一般在`onCreate()`中初始化)
    作为一个纯数据维护工具,可以加入到MVP架构中负责数据保存。
    而官方推选作为AAC架构MVVM中的VM层。

    ViewModel的主要类:

    • ViewModel (下称VM)
      数据储存类,架构的核心类。
      使用时,直接继承该类,根据需求选择重写onCleared()方法。
      如需在Activity被系统销毁后依然保存数据,定义一个参数为(SavedStateHandle)的构造方法,并将数据保存SavedStateHandle中。
      实际上通过SavedInstanceState存取

    • AndroidViewModel
      VM子类,维护了Application的引用,由架构中的SavedStateViewModelFactory创建时传入。
      同样,需要接收SavedStateHandle时,需要定义参数为 (Application, SavedStateHandle)的构造方法。

    • ViewModelStore
      用于保存VM,内部维护了一个用于储存VMHashMap
      一般情况下,直接使用本类创建实例。

    • ViewModelStoreOwner
      接口,实现该接口的类,表示自身能够向外提供VM
      androidx 的AppCompatActivity/Fragment实现了该接口。

    • ViewModelProvider
      VM的提供者,获取VM的基本入口。
      实际依赖ViewModelStore存取VMFactory生成/恢复VM

    • Factory
      接口,实现该接口的类主要用于创建VM实例。
      不建议直接实现该接口,除非你清楚框架内容和自己的需求。
      一般情况下,如果无需SavedStateHandle机制,可以使用AndroidViewModelFactory
      否则应该使用或继承SavedStateViewModelFactory


    ViewModel的基本使用:

    • 一般使用:
    // VM
    class ViewModelA : ViewModel()
    // AVM
    class ViewModelB(app: Application) : AndroidViewModel(app)
    
    // Activity/Fragment .onCreate中
    override fun onCreate() {
      ...
      val provider = ViewModelProvider(this)
      val vmA = provider.get(ViewModelA::class.java)
      val vmB = provider.get(ViewModelB::class.java)
      ...
    }
    
    • 接受 SavedStateHandle
    // VM
    class ViewModelC(
            val handle: SavedStateHandle
    ) : ViewModel()
    
    // AVM
    class ViewModelD(
            app: Application, 
            val handle: SavedStateHandle
    ) : AndroidViewModel(app)
    
    • 跨 Fragment 共享数据
      Fragment中直接以Activity作为ViewModel的Key
    ...
    val provider = ViewModelProvider(requireActivity())
    val vmA = provider.get(ViewModelA::class.java)
    
    • 通过 Application 创建全局共享的 VM
    class App : Application(), ViewModelStoreOwner {
        private lateinit var mAppViewModelStore: ViewModelStore
        private lateinit var mFactory: ViewModelProvider.Factory
    
        override fun onCreate() {
            super.onCreate()
            mAppViewModelStore = ViewModelStore()
            mFactory = ViewModelProvider
                          .AndroidViewModelFactory
                          .getInstance(this)
        }
    
        override fun getViewModelStore(): ViewModelStore {
            return mAppViewModelStore
        }
    
        private fun getAppFactory(): ViewModelProvider.Factory {
            return mFactory
        }
    
        fun getAppViewModelProvider(activity: Activity): ViewModelProvider {
            val app = checkApplication(activity) as App
            return ViewModelProvider(app, app.getAppFactory())
        }
    
        fun getAppViewModelProvider(fragment: Fragment): ViewModelProvider {
            return getAppViewModelProvider(fragment.requireActivity())
        }
    
        private fun checkApplication(activity: Activity): Application {
            return activity.application
                    ?: throw IllegalStateException(
                          "Your activity is not yet attached to the Application instance." + 
                          "You can't request ViewModel before onCreate call.")
        }
    }
    

    ViewModel的关键源码分析:

    以下源码分析将会去除非相关代码以简化

    • ViewModelProvider 实现相关:

    前面提到,ViewModelProvider的工作完全依赖传入的ViewModelStoreFactory,可以直接从构造方法得知:

    ViewModelProvider.java
    ----------------------
    
    private final Factory mFactory;
    private final ViewModelStore mViewModelStore;
    
    public ViewModelProvider(ViewModelStoreOwner owner) {
      this(owner.getViewModelStore(), 
            owner instanceof HasDefaultViewModelProviderFactory
            ? ((HasDefaultViewModelProviderFactory) owner)
                .getDefaultViewModelProviderFactory()
            : NewInstanceFactory.getInstance());
    }
    
    public ViewModelProvider(ViewModelStoreOwner owner, Factory factory) {
        this(owner.getViewModelStore(), factory);
    }
    
    public ViewModelProvider(ViewModelStore store, Factory factory) {
        mFactory = factory;
        mViewModelStore = store;
    }
    
    // 简单的反射创建实例的工厂
    public static class NewInstanceFactory implements Factory {
        public <T extends ViewModel> T create(Class<T> modelClass) {
            return modelClass.newInstance()
        }
    }
    

    androidx.activity.ComponentActivityandroidx.fragment.app.Fragment都实现了ViewModelStoreOwnerHasDefaultViewModelProviderFactory接口。

    public class AppCompatActivity extends FragmentActivity...{}
    public class FragmentActivity extends ComponentActivity...{}
    
    public class ComponentActivity extends ... implements
            ViewModelStoreOwner,
            HasDefaultViewModelProviderFactory,
            SavedStateRegistryOwner ... {}
    
    public class Fragment implements 
            ViewModelStoreOwner, 
            HasDefaultViewModelProviderFactory, 
            SavedStateRegistryOwner ... {}
    

    ViewModelProviderget()方法中返回VM实例,其中mFactorySavedStateViewModelFactory

    ViewModelProvider.java
    ----------------------
    
    private static final String DEFAULT_KEY 
          = "androidx.lifecycle.ViewModelProvider.DefaultKey";
    
    public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }
    
    public <T extends ViewModel> T get(String key, Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);
    
        // 一个确保机制
        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        }
    
        // 正常以及基本的逻辑
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);
        } else {
            viewModel = (mFactory).create(modelClass);
        }
    
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }
    

    SavedStateViewModelFactory在后面解析。


    • ViewModel 的屏幕横竖屏切换恢复机制:

    前面说到,创建VM是通过ViewModelProvider实现的,而ViewModelProvider又是依赖ViewModelStore进行VM的保存。
    当使用ComponentActivity/Fragment作为ViewModelProvider的初始化参数时,实际VM的储存容器是参数提供的。

    1. ComponentActivity 实现:

    从源码中,可以看出横竖屏切换是直接通过NonConfigurationInstances进行恢复的。

    ComponentActivity包含一个NonConfigurationInstances类,其中持有ViewModelStore的引用:

    ComponentActivity.java
    ----------------------
    
    static final class NonConfigurationInstances {
        Object custom;
        ViewModelStore viewModelStore;
    }
    

    保存ViewModelStore
    通过onRetainNonConfigurationInstance()在横竖屏切换中保存ViewModelStore

    ComponentActivity.java
    ----------------------
    
    public final Object onRetainNonConfigurationInstance() {
        Object custom = onRetainCustomNonConfigurationInstance();
    
        // 从上一个 NonConfigurationInstances 中恢复 ViewModelStore
        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            NonConfigurationInstances nc = 
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
    
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }
    
        if (viewModelStore == null && custom == null) {
            return null;
        }
        
        // 保存当前 ViewModelStore
        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;
        return nci;
    }
    

    在使用时尝试通过getLastNonConfigurationInstance()恢复ViewModelStore

    ComponentActivity.java
    ----------------------
    
    public ViewModelStore getViewModelStore() {
        if (mViewModelStore == null) {
            NonConfigurationInstances nc = 
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
    
            if (nc != null) {
                // 通过 NonConfigurationInstances 对象直接恢复 ViewModelStore
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
        return mViewModelStore;
    }
    
    1. Fragment 实现:

    要看懂该部分源码,需要对FragmentManager有基础了解,参考:深入理解FragmentManager

    FragmentViewModelStoreFragmentManager维护的FragmentManagerViewModel管理。

    • 注意这里使用了一个VM来维护一个ViewModelStore
    Fragment.java
    -------------
    
    public ViewModelStore getViewModelStore() {
        return mFragmentManager.getViewModelStore(this);
    }
    
    
    FragmentManager.java
    --------------------
    
    private FragmentManagerViewModel mNonConfig;
    
    ViewModelStore getViewModelStore(Fragment f) {
        return mNonConfig.getViewModelStore(f);
    }
    

    处理FragmentManagerViewModel的实例化:

    FragmentManager.java
    --------------------
    
    void attachController(FragmentHostCallback<?> host, 
                          FragmentContainer container,
                          final Fragment parent) {
        mHost = host;
        mParent = parent;
    
        if (parent != null) {
            // 从父类的FM中获取
            mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
        } else if (host instanceof ViewModelStoreOwner) {
            // 假如 host 对象是实现了 ViewModelStoreOwner
            // 则使用这个ViewModelStoreOwner的viewModelStore创建一个 FragmentManagerViewModel
            ViewModelStore viewModelStore = 
                    ((ViewModelStoreOwner) host).getViewModelStore();
            mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
        } else {
            // 生成一个不支持自动保存ViewModel的 FragmentManagerViewModel
            mNonConfig = new FragmentManagerViewModel(false);
        }
    }
    

    但从源码注释可以了解到,第三种情况已废弃,理想情况下并不支持。


    所以基本上,出现的应该为第一、第二种情况。

    host对象实际是实现的ViewModelStoreOwner接口的FragmentActivity$HostCallbacks

    FragmentActivity.java
    ---------------------
    
    class HostCallbacks 
                extends FragmentHostCallback<FragmentActivity> 
                implements ViewModelStoreOwner ... {...}
    

    第二种情况,attachController()传入参数为null,可以理解为直接附着在FragmentActivity上的Fragment:

    FragmentActivity.java
    ---------------------
    
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);
    }
    
    
    FragmentController.java
    -----------------------
    
    public void attachHost(Fragment parent) {
        mHost.mFragmentManager.attachController(mHost, mHost, parent);
    }
    

    而第一种情况,attachController()传入参数为Fragment,在FragmentperformAttach()中调用:

    Fragment.java
    -------------
    
    void performAttach() {
        mChildFragmentManager.attachController(mHost, new FragmentContainer(), this)
    }
    

    ...
    解决了FragmentManagerViewModel的来源,下面看看它的作用。
    上文提到,FragmentManagerViewModel是一个VM,实际上可以联想到可能是通过ActivityViewModelStore,使用相同的NonConfigurationInstances机制实现的恢复。

    先看第二种情况:

    FragmentManager.java
    --------------------
    
    ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
    mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
    

    其中的hostFragmentActivity$HostCallbacks,而getViewModelStore()返回的实际上是FragmentActivityViewModelStore

    FragmentActivity$HostCallbacks.java
    -----------------------------------
    
    public ViewModelStore getViewModelStore() {
        return FragmentActivity.this.getViewModelStore();
    }
    

    FragmentManagerViewModel.getInstance()内部实际上是通过ViewModelProvider返回一个本类VM实例:

    FragmentManagerViewModel .java
    ------------------------------
    
    static FragmentManagerViewModel getInstance(ViewModelStore viewModelStore) {
        ViewModelProvider viewModelProvider = 
                    new ViewModelProvider(viewModelStore, FACTORY);
        return viewModelProvider.get(FragmentManagerViewModel.class);
    }
    

    由于VM在创建时,会被储存到对应的ViewModelStore,所以该VM会存放到FragmentActivityViewModelStore中。

    第一种情况:
    实际上是顶级FragmentManagerFragmentManagerViewModel中,维护一个子级的FragmentManagerViewModel仓库,然后通过顶级FragmentManagerViewModel直接维护所有子级FragmentManagerViewModel

    FragmentManagerViewModel .java
    ------------------------------
    
    private final HashMap<String, FragmentManagerViewModel> mChildNonConfigs = new HashMap<>();
    
    FragmentManagerViewModel getChildNonConfig(@NonNull Fragment f) {
        FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho);
        if (childNonConfig == null) {
            childNonConfig = new FragmentManagerViewModel(mStateAutomaticallySaved);
            mChildNonConfigs.put(f.mWho, childNonConfig);
        }
        return childNonConfig;
    }
    

    ...
    从以上源码中可以看出,Fragment的横竖屏切换恢复机制实际上是:

    • 通过一个持有自身ViewModelStore引用的VM,依附到ActivityViewModelStore中,通过Activity的机制进行恢复。

    其实这里引申一点的是,源码中提及到,NonConfigurationInstances机制有可能在调用getLastNonConfigurationInstance时返回null,如需确保横竖屏切换时的数据保存,可以使用FragmentonSaveInstanceState(true),以Fragment作为保存数据的容器。


    而事实上,在旧版的ViewModel中,确实是通过FragmentonSaveInstanceState(true)进行的。
    • ViewModel 的后台销毁恢复机制:

    前文提到,SavedStateViewModelFactory是实现该机制的一部分,由SavedStateViewModelFactory生成的VM才具有在后台销毁前后通过SavedStateHandle存取数据的特性。


    先看SavedStateViewModelFactory的构造方法:

    SavedStateViewModelFactory.java
    -------------------------------
    
    public SavedStateViewModelFactory(Application application,
                                      SavedStateRegistryOwner owner,
                                      Bundle defaultArgs) {
    
        mSavedStateRegistry = owner.getSavedStateRegistry();
        mLifecycle = owner.getLifecycle();
        mDefaultArgs = defaultArgs;
        mApplication = application;
        mFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);
    }
    

    SavedStateViewModelFactoryComponentActivity中实例化传入的参数为:

    ComponentActivity.java
    ----------------------
    
    mDefaultFactory = new SavedStateViewModelFactory(
                                getApplication(), 
                                this, 
                                getIntent() != null ? getIntent().getExtras() : null);
    

    ComponentActivity实现了SavedStateRegistryOwner接口,该接口的实现类可以提供SavedStateRegistry实例。


    SavedStateRegistry即是流程的关键对象之一。
    这里涉及到androidx提供的一个新的组件androidx.savedstate:"该组件允许以插件方式,将组件添加到SaveInstanceState过程中"。

    个人理解:
    这是一套针对SavedState操作Bundle的封装工具,但仅适用于系统实现。
    因为流程繁琐,系统源码在实现的过程中还包含了自动重建,自动还原数据,生命周期确保等一系列操作。
    而且当你实现关键的SavedStateProvider接口时,同样要编写Bundle,这和传统的onSaveInstanceState()区别不大。
    因为系统实现了对VM提供的存取操作,建议直接使用VM,或者直接在onSaveInstanceState()对数据进行操作。

    我后面有空会另行写一篇文章去讨论系统对该组件的实现。


    ComponentActivity实例化时,创建成员SavedStateRegistryController,后者实例化时,创建成员SavedStateRegistry

    ComponentActivity.java
    ----------------------
    
    private final SavedStateRegistryController mSavedStateRegistryController =
                    SavedStateRegistryController.create(this);
    
    
    SavedStateRegistryController.java
    ---------------------------------
    
    public static SavedStateRegistryController create(SavedStateRegistryOwner owner) {
        return new SavedStateRegistryController(owner);
    }
    
    private SavedStateRegistryController(SavedStateRegistryOwner owner) {
        mOwner = owner;
        mRegistry = new SavedStateRegistry();
    }
    

    ComponentActivityonSaveInstanceState()中调用SavedStateRegistryController.performSave(),内部实际调用SavedStateRegistry.performSave()

    ComponentActivity.java
    ----------------------
    
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mSavedStateRegistryController.performSave(outState);
    }
    
    
    SavedStateRegistryController.java
    ---------------------------------
    
    public void performSave(Bundle outBundle) {
        mRegistry.performSave(outBundle);
    }
    

    SavedStateRegistry会把所有注册到自身的SavedStateProvider,通过saveState()提取数据,并保存到一个Bundle中:

    SavedStateRegistry.java
    -----------------------
    
    void performSave(@NonNull Bundle outBundle) {
        Bundle components = new Bundle();
        for (Iterator<Map.Entry<String, SavedStateProvider>> it = 
                        mComponents.iteratorWithAdditions(); it.hasNext(); ) {
    
            Map.Entry<String, SavedStateProvider> entry1 = it.next();
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }
    

    至此,说明数据保存的发起,最终通知到SavedStateRegistry


    先看SavedStateProvider接口:

    注册到SavedStateRegistry中实现类,会在SavedStateRegistry保存过程将会调用saveState()获取数据。
    而稍后(在恢复数据时),将会通过SavedStateRegistry.consumeRestoredStateForKey()取出保存的数据。

    SavedStateRegistry$SavedStateProvider.java

    SavedStateProvider通过SavedStateRegistry.registerSavedStateProvider()注册到SavedStateRegistry

    SavedStateRegistry.java
    -----------------------
    
    public void registerSavedStateProvider(String key, SavedStateProvider provider) {
        SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
        if (previous != null) {
            throw new IllegalArgumentException(
                    "SavedStateProvider with the given key is already registered");
        }
    }
    

    到此,说明储存数据的提供者,是注册到SavedStateRegistry中的SavedStateProvider


    前文提及,VM的存取核心是SavedStateHandle,那么说明SavedStateProviderSavedStateHandle存在必然的关联。
    实际上,SavedStateHandle实例中,维护一个SavedStateProvider匿名内部类实例,而SavedStateHandle的读写和SavedStateProvider实例的数据读取操作,都是对实际数据容器mRegular读写。

    先看SavedStateHandle

    • 前文提到,最终该机制的实现,实际为SaveInstanceState机制,则反映VM并不会对数据进行自动存取。
      事实上VM确实需要手动将后台销毁前保存的数据放到SaveInstanceState中,SavedStateHandle确实是这么用的,所以提供了一系列的get/set操作,而最终还要编写SavedStateProviderBundle转换操作。

    • 同时可以看出,SavedStateHandle提供了对LiveData的存取支持。
      SavedStateHandleLiveData的支持,来自对LiveData的内部的静态包装类SavingStateLiveData
      SavingStateLiveData包装了setValue(),传入的参数会被优先储存到mRegular中。

    用于提取数据的SavedStateProvider

    需要编写SavedStateProvider数据的Bundle转换操作。
    所以如无必要,无需自定义该组件,建议在onSaveInstanceState()中直接操作。

    SavedStateHandle.java
    ---------------------
    
    // 最终的数据容器主体
    // initialState为构造时参入的上次SavedInstanceState产生的旧数据
    // 既 SavedStateHandle.createHandle 时传入的参数,下面会说明
    final Map<String, Object> mRegular = new HashMap<>(initialState);
    
    // SavedStateProvider 对数据主体 mRegular 进行处理并生成一个Bundle
    private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() {
            public Bundle saveState() {
                Set<String> keySet = mRegular.keySet();
                ArrayList keys = new ArrayList(keySet.size());
                ArrayList value = new ArrayList(keys.size());
                for (String key : keySet) {
                    keys.add(key);
                    value.add(mRegular.get(key));
                }
                Bundle res = new Bundle();
                // "parcelable" arraylists - lol
                res.putParcelableArrayList("keys", keys);
                res.putParcelableArrayList("values", value);
                return res;
            }
    };
    

    至此,SavedStateHandleSavedStateProvider实现关联。


    前文提及,SavedStateProvider通过SavedStateRegistry.registerSavedStateProvider()注册到SavedStateRegistry

    而该方法的调用,则是通过SavedStateHandleController进行的。
    SavedStateHandleController的实例化则是通过SavedStateViewModelFactory进行的,最终回到了SavedStateViewModelFactory

    先看SavedStateViewModelFactory

    通过调用SavedStateHandleController.create()返回SavedStateHandleController实例。
    同时,VM在创建时,传入了SavedStateHandleControllerSavedStateHandle实例作为参数,即VMSavedStateHandle进行了绑定。

    SavedStateViewModelFactory.java
    -------------------------------
    
    public <T extends ViewModel> T create(String key, Class<T> modelClass) {
    
        // 判断是否是AVM
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor<T> constructor;
        if (isAndroidViewModel) {
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
    
        // 如果不需要SavedStateHandle,则直接创建一个普通的VM/AVM
        if (constructor == null) {
            return mFactory.create(modelClass);
        }
    
        // 创建了 SavedStateHandleController 
        SavedStateHandleController controller = SavedStateHandleController.create(
                                    mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
    
        // VM 在创建的时候持有了SavedStateHandleController内维护的SavedStateHandle对象
        try {
            T viewmodel;
            if (isAndroidViewModel) {
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            return viewmodel;
            ...
    }
    

    再看SavedStateHandleController .create()

    SavedStateHandle在实例化时,通过consumeRestoredStateForKey()传入上次保存的数据,此时SavedStateHandle数据已完成恢复。
    SavedStateHandleController创建后,通过attachToLifecycle()方法,在方法内部将SavedStateHandle维护的SavedStateProvider注册到SavedStateRegistry

    前面说到SavedStateViewModelFactory是框架骨架之一,实际就是通过这个过程,最终允许VM能够把数据的存取加入到SaveInstanceState流程。

    SavedStateHandleController.java
    -------------------------------
    
    static SavedStateHandleController create(SavedStateRegistry registry, 
                          Lifecycle lifecycle, String key, Bundle defaultArgs) {
    
        // 通过consumeRestoredStateForKey获取前次状态
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
        // 创建一个Handle
        SavedStateHandle handle = 
                    SavedStateHandle.createHandle(restoredState, defaultArgs);
    
        // 生成SavedStateHandleController实例
        SavedStateHandleController controller = 
                    new SavedStateHandleController(key, handle);
    
        // 这里进行了绑定
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }
    
    void attachToLifecycle(SavedStateRegistry registry, Lifecycle lifecycle) {
        registry.registerSavedStateProvider(mKey, mHandle.savedStateProvider());
    }
    

    至此,SavedStateProviderSavedStateRegistry实现关联。


    以上就是整个保存流程的概况,而还原流程差距不大,只是在onCreate()中调用SavedStateRegistryController.performRestore(),最终通知SavedStateRegistryBundle中恢复设置的数据。


    忽略SavedStateHandleControllerVM的确保机制 (包含Recreator),最后总结:

    • 简化称呼以缩短阅读量:
      --
      VM组:
      ViewModel = VM
      SavedStateViewModelFactory = Factory
      --
      Registry组:
      SavedStateRegistryController = RegistryController
      SavedStateRegistry = Registry
      --
      Handle组:
      SavedStateHandleController = HandleController
      SavedStateHandle = Handle
      --
      Provider组:
      SavedStateProvider = Provider
      --
    • 初始化阶段:
      ComponentActivity创建了RegistryController实例
      RegistryController创建了内部的Registry实例
      ComponentActivity创建了Factory,并传入RegistryController维护的Registry

    • 恢复阶段
      ComponentActivityonCreate调用RegistryControllerperformRestore
      RegistryControllerperformRestore中,调用RegistryperformRestore
      RegistryperformRestore中,把数据从savedInstanceState (Bundle)取出,并储存到mRestoredState
      在此处Registry已把数据恢复

    • VM生成阶段:
      VM需要通过Factory创建,创建过程:
      -- 创建VM对应的HandleController实例,创建过程:
      ------ 通过RegistryconsumeRestoredStateForKey把数据取出生成Handle
      ------ Handle内部维护一个Provider实例,共享数据容器mRegular
      ------ HandleController被注入Handle
      ------ Provider绑定到Registry
      ------ 在此处实现了 (RegistryController-Registry-Provider-Handle) 绑定
      --VMFactory注入Handle
      --在此处实现了 (RegistryController-Registry-Provider-Handle-VM) 绑定
      --VM数据最终通过Registry恢复

    • 写数据阶段
      VM读写的数据最终存放到HandlemRegular
      VM数据最终通过Registry保存

    • 保存阶段
      ComponentActivityonSaveInstanceState调用RegistryControllerperformSave
      RegistryControllerperformSave中,调用RegistryperformSave
      RegistryperformSave中,将所有注册的Provider数据打包成一个Bundle保存到onSaveInstanceStateBundle
      在此处Registry已把数据保存

    ·

    相关文章

      网友评论

        本文标题:深入理解AAC架构 - ViewModel 使用以及整体机制源码

        本文链接:https://www.haomeiwen.com/subject/hrtzfhtx.html