Android JetPack学习笔记-ViewModel

目录

1、横竖屏切换        

2.ViewModel如何存放的,以及生命周期如何。

3.系统资源限制导致的activity销毁-数据恢复

        1、保存

        2.恢复

        3.后续的入口和消费


1、横竖屏切换        

        了解ViewModel总是会先说,它横竖屏数据不会消失。熟悉AMS和启动的应该知道横竖屏时配置更改会调用ActivityThread.

    private void handleRelaunchActivityInner(ActivityClientRecord r, int configChanges,
            List pendingResults, List pendingIntents,
            PendingTransactionActions pendingActions, boolean startsNotResumed,
            Configuration overrideConfig, String reason) {
        ......
        handleDestroyActivity(r, false, configChanges, true, reason);
       
        r.activity = null;
        r.window = null;
        r.hideForNow = false;
        r.nextIdle = null;
        ......
        handleLaunchActivity(r, pendingActions, customIntent);
    }

        重新启动先后执行handleDestoryActivity和handleLaunchActivity。先销毁再启动。

    public void handleDestroyActivity(ActivityClientRecord r, boolean finishing, int configChanges,
            boolean getNonConfigInstance, String reason) {
        performDestroyActivity(r, finishing, configChanges, getNonConfigInstance, reason);
        ......
    }


    void performDestroyActivity(ActivityClientRecord r, boolean finishing,
            int configChanges, boolean getNonConfigInstance, String reason) {
        ......
        //先执行pause
        performPauseActivityIfNeeded(r, "destroy");

        if (!r.stopped) {
            callActivityOnStop(r, false /* saveState */, "destroy");
        }
        if (getNonConfigInstance) {
            try {
                //需要对NonConfigurationInstances有一个印象,后边有使用到
                //这里调用到了activity的retainNonConfigurationInstances方法
                r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();
            } catch (Exception e) {
                if (!mInstrumentation.onException(r.activity, e)) {
                    throw new RuntimeException("Unable to retain activity "
                            + r.intent.getComponent().toShortString() + ": " + e.toString(), e);
                }
            }
        }
        try {
            r.activity.mCalled = false;
            //最后执行destory
            mInstrumentation.callActivityOnDestroy(r.activity);
            ......
        }
        ......
    }

        代码里有注释,不多讲解了。这么看时序就是onPause->onStop->retainNonConfigurationInstances->onDestory。retainNonConfigurationInstances不太常见,看看。

    //Activity里的方法
    NonConfigurationInstances retainNonConfigurationInstances() {
        Object activity = onRetainNonConfigurationInstance();
        HashMap children = onRetainNonConfigurationChildInstances();
        FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();

        mFragments.doLoaderStart();
        mFragments.doLoaderStop(true);
        ArrayMap loaders = mFragments.retainLoaderNonConfig();

        if (activity == null && children == null && fragments == null && loaders == null
                && mVoiceInteractor == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.activity = activity;
        nci.children = children;
        nci.fragments = fragments;
        nci.loaders = loaders;
        if (mVoiceInteractor != null) {
            mVoiceInteractor.retainInstance();
            nci.voiceInteractor = mVoiceInteractor;
        }
        return nci;
    }

    public Object onRetainNonConfigurationInstance() {
        return null;
    }

        可以看出这个方法把activity的基本信息都获取到了,然后返回。其中onRetainNonConfigurationInstance方法和onRetainNonConfigurationChildInstances方法都是返回null且是public声明,就要去看子类了。ComponentActivity

    static final class NonConfigurationInstances {
        Object custom;
        ViewModelStore viewModelStore;
    }

    public final Object onRetainNonConfigurationInstance() {
        // Maintain backward compatibility.
        Object custom = onRetainCustomNonConfigurationInstance();

        ViewModelStore viewModelStore = mViewModelStore;
        if (viewModelStore == null) {
            // No one called getViewModelStore(), so see if there was an existing
            // ViewModelStore from our last NonConfigurationInstance
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                viewModelStore = nc.viewModelStore;
            }
        }

        if (viewModelStore == null && custom == null) {
            return null;
        }

        NonConfigurationInstances nci = new NonConfigurationInstances();
        nci.custom = custom;
        nci.viewModelStore = viewModelStore;
        return nci;
    }

        看出来ComponentActvity中主要就是把viewModelStore存储过去了。这个类后续讲。走完destory,就该走launchActivity了。继续回到ActivityThread中。

    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        ......

        final Activity a = performLaunchActivity(r, customIntent);
        ......
    }

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ......
        try {
            ......

            if (activity != null) {
               ......
                //在ondestory存的信息正attach方法全部都放回去了
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback,
                        r.assistToken, r.shareableActivityToken);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                ......
                r.activity = activity;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }

                ......
            ......
        return activity;
    }

        可以看到这LauchActivity中的时序,先attach->onCreate。

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
            IBinder shareableActivityToken) {
        attachBaseContext(context);

        ......
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        ......
    }

        attach其他的我都注释了,大概就是把信息全部都赋值。咱们需要注意的是这个mLastNonConfiguration就好了。咱们内部源码就走完了。感觉什么都不知道,但是重要的是被销毁的activity的NonConfigurationInstance存储在了mlastNonConfiguration中。后边我们只需要从中拿出来渲染即可。

        在咱们获取ViewModelStore时,就会获取mlastNonConfiguration,判断它是否为空,不为空就直接使用。

//-----ViewModelProvider-----
    public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
        this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
                ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
                : NewInstanceFactory.getInstance());
    }

//-----ComponentActivity-----

    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.");
        }
        ensureViewModelStore();
        return mViewModelStore;
    }

    void ensureViewModelStore() {
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                //到这一步使用之前的ViewModelStore,其存着之前的ViewModel。这样数据就恢复了
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
    }

2.ViewModel如何存放的,以及生命周期如何。

    public  T get(@NonNull Class modelClass) {
        String canonicalName = modelClass.getCanonicalName();
        if (canonicalName == null) {
            throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
        }
        return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
    }

    public  T get(@NonNull String key, @NonNull Class modelClass) {
        //如果ViewModelStore中存在这样的ViewModel就直接使用
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
        } else {
            viewModel = mFactory.create(modelClass);
        }
        //讲ViewModel实例存放在ViewModelStore中
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

        获取ViewModel实例时的get方法就有存放的代码,如果之前恢复的ViewModelStore中有对应的ViewModel就直接使用,没有就通过工厂实例个存入ViewModelStore中并返回。

        那生命周期又是怎样,为什么说它比activity生命周期长?

    public ComponentActivity() {
        ......
        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    // Clear out the available context
                    mContextAwareHelper.clearAvailableContext();
                    // And clear the ViewModelStore
                    //判断配置是否发生改变
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                }
            }
        });
        ......

    }

        相信大家都知道lifecycle组件,这里添加了观察者,总结:在生命周期为On_Destory时会进行ViewModelStore的清除,但是存在一个if,这个if判断是否配置发生改变。如果不是因为配置发生改变而销毁的Activity,ViewModelStore是会清除的。

//-----ViewModelStore------
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            vm.clear();
        }
        mMap.clear();
    }

//-----ViewModel-----
    @MainThread
    final void clear() {
        mCleared = true;

        if (mBagOfTags != null) {
            synchronized (mBagOfTags) {
                for (Object value : mBagOfTags.values()) {
                    // see comment for the similar call in setTagIfAbsent
                    closeWithRuntimeException(value);
                }
            }
        }
        onCleared();
    }

        clear没啥可说的,就把ViewModelStore中的所有ViewModel都执行onCleared销毁方法。

        看看ComponentActivity构造函数中的另一个观察者。

    public ComponentActivity() {

        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                ensureViewModelStore();
                getLifecycle().removeObserver(this);
            }
        });
    }

        其实早在实例化activity时就已经去获取ViewModelStore了。所以在onCreate前就恢复了我们ViewModel的数据。说恢复其实也不太好,因为和上一个activity用的ViewModel完全是同一个实例对象。

        总结:横竖屏切换数据恢复

        1.首先ComponentActivity中的NonConfigurationInstances有ViewModelStore的实例,ViewModel存储在ViewModelStore中。

        2.横竖屏切换时,ActivityThread会先后执行Destory和Lauch,在Destory中先后执行Pause、Stop、retainNonConfigurationInstances和Destory。retainNonConfigurationInstances在Activity中,它会去获取ComponentActivity中的NonConfigurationInstances存入到自身的NonConfigurationInstances变量中。然后存储到ActivityThread里的ActivityClientRecord中。

        3.执行Lauch时,会先后执行attach和create。Activity中的attach主要做的事情就是把之前保存到ActivityClientRecord中的数据,取出来。其中NonConfigurationInstances存储在Activity的mLastNonConfigurationInstances变量里的activity。

        4.在重新创建ViewModel时,会去获取上次的NonConfigurationInstances。如果之前的ViewModelStore中存在相应的ViewModel就直接去除,这个对应的ViewModel中就存储着之前的数据。

3.系统资源限制导致的activity销毁-数据恢复

        1、保存

    final SavedStateRegistryController mSavedStateRegistryController =
            SavedStateRegistryController.create(this);

    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Lifecycle lifecycle = getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
        }
        super.onSaveInstanceState(outState);
        mSavedStateRegistryController.performSave(outState);
        mActivityResultRegistry.onSaveInstanceState(outState);
    }

        看到有调用performSave方法。是SavedStateRegistryController类调用的。

public final class SavedStateRegistryController {
    private final SavedStateRegistryOwner mOwner;
    private final SavedStateRegistry mRegistry;

    private SavedStateRegistryController(SavedStateRegistryOwner owner) {
        mOwner = owner;
        mRegistry = new SavedStateRegistry();
    }

    @NonNull
    public SavedStateRegistry getSavedStateRegistry() {
        return mRegistry;
    }

    @MainThread
    public void performRestore(@Nullable Bundle savedState) {
        Lifecycle lifecycle = mOwner.getLifecycle();
        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
            throw new IllegalStateException("Restarter must be created only during "
                    + "owner's initialization stage");
        }
        lifecycle.addObserver(new Recreator(mOwner));
        mRegistry.performRestore(lifecycle, savedState);
    }

    @MainThread
    public void performSave(@NonNull Bundle outBundle) {
        mRegistry.performSave(outBundle);
    }

    @NonNull
    public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
        return new SavedStateRegistryController(owner);
    }
}

        发现 SavedStateRegistryController内部实现都是SavedStateRegistry。它持有着我们activity和SavedStateRegistry。继续看SavedStateRegistry.performSave

    void performSave(@NonNull Bundle outBundle) {
        Bundle components = new Bundle();
        if (mRestoredState != null) {
            components.putAll(mRestoredState);
        }
        for (Iterator> it =
                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
            Map.Entry entry1 = it.next();
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }

         就是把我们要保存的数据,存入传过来的bundle中。我们需要对mComponents和saveState保持印象。

        2.恢复

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // Restore the Saved State first so that it is available to
        // OnContextAvailableListener instances
        mSavedStateRegistryController.performRestore(savedInstanceState);
        mContextAwareHelper.dispatchOnContextAvailable(this);
        super.onCreate(savedInstanceState);
        mActivityResultRegistry.onRestoreInstanceState(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }

        跟保存用的是同一个类调用了performRestore,直接进入SavedStateRegistry中看代码吧。

    void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
        if (mRestored) {
            throw new IllegalStateException("SavedStateRegistry was already restored.");
        }
        if (savedState != null) {
            mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
        }

        lifecycle.addObserver(new GenericLifecycleObserver() {
            @Override
            public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_START) {
                    mAllowingSavingState = true;
                } else if (event == Lifecycle.Event.ON_STOP) {
                    mAllowingSavingState = false;
                }
            }
        });

        mRestored = true;
    }

        如果有数据需要恢复就从传过来的bundle中获取 key为SAVED_COMPONENTS_KEY的bundle。赋值给mRestoredState。

        3.后续的入口和消费

val viewModel by lazy { ViewModelProvider(this).get(WeatherViewModel::class.java) }

        实例ViewModelProvider已经分析过了,直接走进get。

    public  T get(@NonNull String key, @NonNull Class modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        if (mFactory instanceof KeyedFactory) {
            //activity默认的工厂类会满足这种情况SavedStateViewModelFactory
            viewModel = ((KeyedFactory) mFactory).create(key, modelClass);
        } else {
            viewModel = mFactory.create(modelClass);
        }
        mViewModelStore.put(key, viewModel);
        return (T) viewModel;
    }

        还记得这个get嘛,如果ViewModelStore中不存在ViewModel就需要使用工厂去实例。

    public SavedStateViewModelFactory(@Nullable Application application,
            @NonNull SavedStateRegistryOwner owner,
            @Nullable Bundle defaultArgs) {
        mSavedStateRegistry = owner.getSavedStateRegistry();   //activity中拿过来的Registry
        mLifecycle = owner.getLifecycle();//activity中的lifecycle
        mDefaultArgs = defaultArgs;//activity中getIntent获取的extras
        mApplication = application;
        mFactory = application != null
                ? ViewModelProvider.AndroidViewModelFactory.getInstance(application)//默认为这个实例
                : ViewModelProvider.NewInstanceFactory.getInstance();
    }


    public  T create(@NonNull String key, @NonNull Class modelClass) {
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor constructor;
        if (isAndroidViewModel && mApplication != null) {
            //获取ViewModel的带有Application.class、SavedStateHandle.class为参数的构造函数
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            //获取ViewModel的带有SavedStateHandle.class为参数的构造函数
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
        // doesn't need SavedStateHandle
        if (constructor == null) {
            //不需要就直接反射创建,这就不考虑销毁后恢复数据了
            return mFactory.create(modelClass);
        }

        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        try {
            T viewmodel;
            //反射生成实例
            if (isAndroidViewModel && mApplication != null) {
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            //将controller存入viewmodel中 key为TAG_SAVED_STATE_HANDLE_CONTROLLER
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            return viewmodel;
        } catch (IllegalAccessException e) {
           ......
        }
    }

        里头注释有详细写,不再赘述。看看SavedStateHandleController这个类。

//-----SavedStateHandleController-----
    SavedStateHandleController(String key, SavedStateHandle handle) {
        mKey = key;
        mHandle = handle;
    }

    static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
        //1.获取需要恢复的数据这个key是ViewModel的类名
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
        //2.创建SavedStateHandle实例,参数为需要恢复的bundle和activity传过来的bundle传入其map中
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
        //3.订阅和给Registry注册SavedStateProvider
        controller.attachToLifecycle(registry, lifecycle);
        //4.给Registry再注册一个和存入key为COMPONENT_KEY的SavedStateProvider  
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

    void attachToLifecycle(SavedStateRegistry registry, Lifecycle lifecycle) {
        if (mIsAttached) {
            throw new IllegalStateException("Already attached to lifecycleOwner");
        }
        mIsAttached = true;
        lifecycle.addObserver(this); //此类继承自LifecycleEventObserver,与生命组件进行订阅
        registry.registerSavedStateProvider(mKey, mHandle.savedStateProvider());//注册key为ViewModel类名的SavedStateProvider存储数据
    }


    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
        if (event == Lifecycle.Event.ON_DESTROY) {
            //当destroy销毁时,移除订阅
            mIsAttached = false;
            source.getLifecycle().removeObserver(this);
        }
    }

    private static void tryToAddRecreator(SavedStateRegistry registry, Lifecycle lifecycle) {
        Lifecycle.State currentState = lifecycle.getCurrentState();
        if (currentState == INITIALIZED || currentState.isAtLeast(STARTED)) {
            //增加一个SavedStateProvider
            registry.runOnNextRecreation(OnRecreation.class);
        } else {
            lifecycle.addObserver(new LifecycleEventObserver() {
                @Override
                public void onStateChanged(@NonNull LifecycleOwner source,
                        @NonNull Lifecycle.Event event) {
                    if (event == Lifecycle.Event.ON_START) {
                        lifecycle.removeObserver(this);
                        //增加一个SavedStateProvider
                        registry.runOnNextRecreation(OnRecreation.class);
                    }
                }
            });
        }
    }

1.获取需要恢复的bundle数据

    public Bundle consumeRestoredStateForKey(@NonNull String key) {
        if (!mRestored) {
            throw new IllegalStateException("You can consumeRestoredStateForKey "
                    + "only after super.onCreate of corresponding component");
        }
        //在onCreate恢复的时候已经将需要恢复的数据存入mRestoredState中了
        if (mRestoredState != null) {
            Bundle result = mRestoredState.getBundle(key);
            mRestoredState.remove(key);
            if (mRestoredState.isEmpty()) {
                mRestoredState = null;
            }
            return result;
        }
        return null;
    }

2.创建SavedStateHandle实例

    public SavedStateHandle(@NonNull Map initialState) {
        mRegular = new HashMap<>(initialState);
    }

    public SavedStateHandle() {
        mRegular = new HashMap<>();
    }

    static SavedStateHandle createHandle(@Nullable Bundle restoredState,
            @Nullable Bundle defaultState) {
        if (restoredState == null && defaultState == null) {
            return new SavedStateHandle();
        }

        Map state = new HashMap<>();
        if (defaultState != null) {
            for (String key : defaultState.keySet()) {
                state.put(key, defaultState.get(key));
            }
        }

        if (restoredState == null) {
            return new SavedStateHandle(state);
        }

        ArrayList keys = restoredState.getParcelableArrayList(KEYS);
        ArrayList values = restoredState.getParcelableArrayList(VALUES);
        if (keys == null || values == null || keys.size() != values.size()) {
            throw new IllegalStateException("Invalid bundle passed as restored state");
        }
        for (int i = 0; i < keys.size(); i++) {
            state.put((String) keys.get(i), values.get(i));
        }
        //将需要恢复的数据存入到mRegular中
        return new SavedStateHandle(state);
    }

3.订阅和给Registry注册SavedStateProvider

//-----SavedStateHandle-----
    private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() {
        @SuppressWarnings("unchecked")
        @NonNull
        @Override
        public Bundle saveState() {
            Map map = new HashMap<>(mSavedStateProviders);
            for (Map.Entry entry : map.entrySet()) {
                Bundle savedState = entry.getValue().saveState();
                set(entry.getKey(), savedState);
            }
            // Convert the Map of current values into a Bundle
            Set 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();
            res.putParcelableArrayList("keys", keys);
            res.putParcelableArrayList("values", value);
            //将需要恢复的mRegular中的数据转成bundle返回
            return res;
        }
    };

    @NonNull
    SavedStateProvider savedStateProvider() {
        return mSavedStateProvider;
    }

//-----SavedStateRegistry-----
    public void registerSavedStateProvider(@NonNull String key,
            @NonNull SavedStateProvider provider) {
        //此时传入的key是ViewModel的类名
        SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
        if (previous != null) {
            throw new IllegalArgumentException("SavedStateProvider with the given key is"
                    + " already registered");
        }
    }

4.给Registry再注册一个和存入key为COMPONENT_KEY的SavedStateProvider  

//-----SavedStateRegistry-----
    public void runOnNextRecreation(@NonNull Class clazz) {
        if (!mAllowingSavingState) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mRecreatorProvider == null) {
            mRecreatorProvider = new Recreator.SavedStateProvider(this);
        }
        try {
            clazz.getDeclaredConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class" + clazz.getSimpleName() + " must have "
                    + "default constructor in order to be automatically recreated", e);
        }
        mRecreatorProvider.add(clazz.getName());
    }

//-----Recreator-----
        SavedStateProvider(final SavedStateRegistry registry) {
            //这里注册的是key为COMPONENT_KEY的SavedStateProvider
            registry.registerSavedStateProvider(COMPONENT_KEY, this);
        }

        如果我们需要在系统限制后恢复数据,ViewModel就需要这么写。 需要提供一个savedStateHandle为参数的构造函数。

class SavedStateViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {

    companion object {
        private const val KEY_NAME = "keyName"
    }

    //通过 SavedStateHandle.getLiveData方法来生成一个 LiveData 对象
    val nameLiveData = savedStateHandle.getLiveData(KEY_NAME)
    val blogLiveData = MutableLiveData()
}

        瞧瞧savedStateHandle.getLiveData代码

//-----SavedStateHandle-----
    public  MutableLiveData getLiveData(@NonNull String key,
            @SuppressLint("UnknownNullness") T initialValue) {
        return getLiveDataInternal(key, true, initialValue);
    }

    private  MutableLiveData getLiveDataInternal(
            @NonNull String key,
            boolean hasInitialValue,
            @Nullable T initialValue) {
        MutableLiveData liveData = (MutableLiveData) mLiveDatas.get(key);
        if (liveData != null) {
            return liveData;
        }
        SavingStateLiveData mutableLd;
        // double hashing but null is valid value
        if (mRegular.containsKey(key)) {
            mutableLd = new SavingStateLiveData<>(this, key, (T) mRegular.get(key));
        } else if (hasInitialValue) {
            mutableLd = new SavingStateLiveData<>(this, key, initialValue);
        } else {
            mutableLd = new SavingStateLiveData<>(this, key);
        }
        mLiveDatas.put(key, mutableLd);
        return mutableLd;
    }

//-----SavedStateHandle-----SavingStateLiveData

    static class SavingStateLiveData extends MutableLiveData {
        private String mKey;
        private SavedStateHandle mHandle;

        SavingStateLiveData(SavedStateHandle handle, String key, T value) {
            super(value);
            mKey = key;
            mHandle = handle;
        }

        @Override
        public void setValue(T value) {
            if (mHandle != null) {
                mHandle.mRegular.put(mKey, value);
            }
            super.setValue(value);
        }
    }

        之前在创建SavedStateHandle实例时,将需要恢复的数据传入了mRegular中。如果mRegular中存在我们需要找的数据就直接返回,这样就起到了恢复数据的目的。不存在就重新创建一个SavingStateLiveData。了解liveData应该了解咱们设置值时会调用setValue,在setValue中又将此值传给了mRegular。

        小结:SaveStateHandle中存着保存的数据。恢复时从bundle中获取到需要恢复的bundle然后将bundle中的值存入到mRegular中,在恢复了ViewModel实例后,通过getLiveData会从mRegular中判断是否存在这样的key对应的value,存在就直接取值。这样消费就走完了。不过保存还没算完


        

    void performSave(@NonNull Bundle outBundle) {
        Bundle components = new Bundle();
        if (mRestoredState != null) {
            components.putAll(mRestoredState);
        }
        for (Iterator> it =
                mComponents.iteratorWithAdditions(); it.hasNext(); ) {
            Map.Entry entry1 = it.next();
            components.putBundle(entry1.getKey(), entry1.getValue().saveState());
        }
        outBundle.putBundle(SAVED_COMPONENTS_KEY, components);
    }

        在save时,通过从SavedStateRegistry中的mComponents中取出对应的SavedStateProvider并且拿到对应SavedStateProvider中保存的数据。

        我们在创建SavedStateHandleController时先后给Registry注册了两个SavedStateProvider。分别是key为ViewModel的和key为COMPONENT_KEY的Provider存入Registry中的mComponents中。

//----此Provider在SavedStateHandle中申明-----
//key为对应ViewModel类名的Provider
    private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() {
        @SuppressWarnings("unchecked")
        @NonNull
        @Override
        public Bundle saveState() {
            Map map = new HashMap<>(mSavedStateProviders);
            for (Map.Entry entry : map.entrySet()) {
                Bundle savedState = entry.getValue().saveState();
                set(entry.getKey(), savedState);
            }
            Set 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();
            res.putParcelableArrayList("keys", keys);
            res.putParcelableArrayList("values", value);
            return res;
        }
    };

//-----Recreator中的类--------
//key为COMPONENT_KEY的Provider
    static final class SavedStateProvider implements SavedStateRegistry.SavedStateProvider {
        @SuppressWarnings("WeakerAccess") // synthetic access
        final Set mClasses = new HashSet<>();

        SavedStateProvider(final SavedStateRegistry registry) {
            registry.registerSavedStateProvider(COMPONENT_KEY, this);
        }

        @NonNull
        @Override
        public Bundle saveState() {
            Bundle bundle = new Bundle();
            bundle.putStringArrayList(CLASSES_KEY, new ArrayList<>(mClasses));
            return bundle;
        }

        void add(String className) {
            mClasses.add(className);
        }
    }

        SavedStateHandle中的Provider存的都是咱们ViewModel中的数据,在保存时通过mRegular转化成bundle,返回。而Recreator中的Provider存的就是class名称了。

    public void runOnNextRecreation(@NonNull Class clazz) {
        //clazz为OnRecreation.class
        if (!mAllowingSavingState) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mRecreatorProvider == null) {
            mRecreatorProvider = new Recreator.SavedStateProvider(this);
        }
        try {
            clazz.getDeclaredConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Class" + clazz.getSimpleName() + " must have "
                    + "default constructor in order to be automatically recreated", e);
        }
        mRecreatorProvider.add(clazz.getName());
    }

        在最后一行给这个Provider添加了OnRecreation的类名称。那在哪里使用到了这个Provider的数据呢?在Restore时有使用到。

//-----SavedStateRegistryController-----
    public void performRestore(@Nullable Bundle savedState) {
        Lifecycle lifecycle = mOwner.getLifecycle();
        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
            throw new IllegalStateException("Restarter must be created only during "
                    + "owner's initialization stage");
        }
        lifecycle.addObserver(new Recreator(mOwner));//这里实例了一个Recretor,它是观察者
        mRegistry.performRestore(lifecycle, savedState);
    }

//-----Recreator-----
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (event != Lifecycle.Event.ON_CREATE) {
            throw new AssertionError("Next event must be ON_CREATE");
        }
        source.getLifecycle().removeObserver(this);
        //从Registry中的mComponents中获取key为COMPONENT_KEY的bundle
        Bundle bundle = mOwner.getSavedStateRegistry()
                .consumeRestoredStateForKey(COMPONENT_KEY);
        if (bundle == null) {
            return;
        }
        //之前存的时候的代码是bundle.putStringArrayList(CLASSES_KEY, new ArrayList<>(mClasses));
        ArrayList classes = bundle.getStringArrayList(CLASSES_KEY);
        if (classes == null) {
            throw new IllegalStateException("Bundle with restored state for the component \""
                    + COMPONENT_KEY + "\" must contain list of strings by the key \""
                    + CLASSES_KEY + "\"");
        }
        for (String className : classes) {
            //循环反射
            reflectiveNew(className);
        }
    }

    //反射出AutoRecreated实例,并调用其onRecreated方法
    private void reflectiveNew(String className) {
        Class clazz;
        try {
            clazz = Class.forName(className, false,
                    Recreator.class.getClassLoader()).asSubclass(AutoRecreated.class);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Class " + className + " wasn't found", e);
        }

        Constructor constructor;
        try {
            constructor = clazz.getDeclaredConstructor();
        } catch (NoSuchMethodException e) {
            throw new IllegalStateException("Class" + clazz.getSimpleName() + " must have "
                    + "default constructor in order to be automatically recreated", e);
        }
        constructor.setAccessible(true);

        AutoRecreated newInstance;
        try {
            newInstance = constructor.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Failed to instantiate " + className, e);
        }
        newInstance.onRecreated(mOwner);
    }

//-----SavedStateRegistryController-----OnRecreation-----
    static final class OnRecreation implements SavedStateRegistry.AutoRecreated {

        @Override
        public void onRecreated(@NonNull SavedStateRegistryOwner owner) {
            if (!(owner instanceof ViewModelStoreOwner)) {
                throw new IllegalStateException(
                        "Internal error: OnRecreation should be registered only on components"
                                + "that implement ViewModelStoreOwner");
            }
            ViewModelStore viewModelStore = ((ViewModelStoreOwner) owner).getViewModelStore();
            SavedStateRegistry savedStateRegistry = owner.getSavedStateRegistry();
            for (String key : viewModelStore.keys()) {
                ViewModel viewModel = viewModelStore.get(key);
                attachHandleIfNeeded(viewModel, savedStateRegistry, owner.getLifecycle());
            }
            if (!viewModelStore.keys().isEmpty()) {
                savedStateRegistry.runOnNextRecreation(OnRecreation.class);
            }
        }
    }

        代码上面有注释,不再赘述。其中onRecreated这个方法看看。

    static void attachHandleIfNeeded(ViewModel viewModel, SavedStateRegistry registry,
            Lifecycle lifecycle) {
        //从ViewModel中取controller,之前创建ViewModel实例是存入的代码是
        //viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
        SavedStateHandleController controller = viewModel.getTag(
                TAG_SAVED_STATE_HANDLE_CONTROLLER);
        if (controller != null && !controller.isAttached()) {
            controller.attachToLifecycle(registry, lifecycle);
            tryToAddRecreator(registry, lifecycle);
        }
    }

        这样恢复的时候,首先把它之前保存且未创建的ViewModel与生命周期关联起来,从ViewModel中拿出之前controller实例,然后进行订阅和注册Registry中的Provider。因为viewmodel不会空不会需要factory取实例就也不会创建controller。所以需要再这边进行后续的订阅和注册Provider等等。其中controller的isAttached的方法在其destory时会变成false,之前咱们也有看到。

        总结:

        1.在创建ViewModel实例时,如果ViewModel中含有SavedStateHandle参数的构造函数,就会使用工厂创建viewmodel实例,工厂创建实例会创建SavedStateHandleController和SavedStateHandle以及给SavedStateRegistry中注册两个Provider,key分别是对应ViewModel的类名(此Provider主要存的是ViewModel中的数据,mRegular)和COMPONENT_KEY(此Provide主要存的是类名称如OnRecreation.class)。

        2.保存时,在onSaveInstanceState中调用了RegistryController的保存方法,它调用Registry中的保存方法将存入的Provider中保存的数据存入bundle中。保存时key依然是之前存Provider的key。全部Provider中的数据以key为SAVED_COMPONENTS_KEY存入传进的bundle中。

        3.恢复时,在onCreate中调用了RegistryController的恢复方法,它调用Registry中的恢复方法。

        (1)首先从传入的bundle中取出key为SAVED_COMPONENTS_KEY的bundle存入mRestoredState成员中。

        (2)给lifecycle添加观察者,此观察者走完onCreate就移除,onCreate时从mRestoredState中获取key为COMPONENT_KEY的bundle数据,通过反射调用onRecreated方法。然后从恢复的ViewModel中获取它的SavedStateHandleController对象,去订阅生命周期和给Registry注册Provider。

        这样ViewModel创建实例后就可以获取到恢复的数据,进行变更渲染UI。


回到get方法中重看一行代码

    public  T get(@NonNull String key, @NonNull Class modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            if (mFactory instanceof OnRequeryFactory) {
                ((OnRequeryFactory) mFactory).onRequery(viewModel);
            }
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        ......
        return (T) viewModel;
    }

        在横竖屏恢复数据时会调用.onRequery(viewModel)方法。

    void onRequery(@NonNull ViewModel viewModel) {
        attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
    }

    static void attachHandleIfNeeded(ViewModel viewModel, SavedStateRegistry registry,
            Lifecycle lifecycle) {
        SavedStateHandleController controller = viewModel.getTag(
                TAG_SAVED_STATE_HANDLE_CONTROLLER);
        if (controller != null && !controller.isAttached()) {
            controller.attachToLifecycle(registry, lifecycle);
            tryToAddRecreator(registry, lifecycle);
        }
    }

        从这边就一下能理解attachHandleIfNeeded方法了吧,通过之前ViewModel拿到Controller,如果不为空且经历过之前销毁就重新给他订阅生命周期和给Registry注册Provider。当然横竖屏所有数据依然在ViewModel中,并没有丢失所以不需要从Registry中重新获取恢复数据。

你可能感兴趣的:(Android,JetPack,android,android,jetpack,学习)