ViewModel源碼閱讀(二)SavedStateHandle的基本數(shù)據(jù)緩存原理

前言

閱讀本篇文章前最好先看上篇文章ViewModel源碼閱讀(一)ViewModel的生命周期
在閱讀SavedStateHandle之前,我們需要搞清上篇文章通過getLastNonConfigurationInstance和onRetainNonConfigurationInstance存儲的數(shù)據(jù),與通過onSaveInstanceState和Bundle存儲的數(shù)據(jù)有什么不同
我這里直接就說出結(jié)論了
getLastNonConfigurationInstance是通過NonConfigurationInstances保存狀態(tài)的,這個(gè)狀態(tài)可以獲取的前提是進(jìn)程沒有被銷毀
onSaveInstanceState中Bundle是通過Parcel保存狀態(tài)的,這種保存的狀態(tài)是非依附于進(jìn)程的,當(dāng)前進(jìn)程被殺死,狀態(tài)也是保留的
詳細(xì)可以參考這篇文章,這里就不展開討論了

在上面邏輯基礎(chǔ)上,和上篇文章分析的ViewModel生命周期,我們可以推測出,ViewModel在進(jìn)程被系統(tǒng)殺死時(shí),再恢復(fù)時(shí),是重新創(chuàng)建實(shí)例的,所以ViewModel引入了SavedStateHandle,來做輕量數(shù)據(jù)狀態(tài)暫存

分析代碼

這塊的代碼我第一次看的時(shí)候有點(diǎn)繞,因?yàn)殛P(guān)聯(lián)類太多了,所以這塊代碼單獨(dú)獨(dú)立出來
下面開始閱讀源碼

  @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass) {
        boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);
        Constructor<T> constructor;
//獲取構(gòu)造函數(shù),判斷是否需要傳入SavedStateHandle
        if (isAndroidViewModel && mApplication != null) {
            constructor = findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE);
        } else {
            constructor = findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE);
        }
        // doesn't need SavedStateHandle
        if (constructor == null) {
            return mFactory.create(modelClass);
        }
//核心方法,用來創(chuàng)建Handle的關(guān)鍵代碼
//此處傳入了一個(gè)mSavedStateRegistry 和mLifecycle 作用暫時(shí)未知
//key和mDefaultArgs分別對應(yīng)ViewModel的唯一標(biāo)識和getIntent中暫存的數(shù)據(jù)
        SavedStateHandleController controller = SavedStateHandleController.create(
                mSavedStateRegistry, mLifecycle, key, mDefaultArgs);
        try {
            T viewmodel;
//下面的代碼就是傳入handle的
            if (isAndroidViewModel && mApplication != null) {
                viewmodel = constructor.newInstance(mApplication, controller.getHandle());
            } else {
                viewmodel = constructor.newInstance(controller.getHandle());
            }
            viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);
            return viewmodel;
        } catch (IllegalAccessException e) {
            throw new RuntimeException("Failed to access " + modelClass, e);
        } catch (InstantiationException e) {
            throw new RuntimeException("A " + modelClass + " cannot be instantiated.", e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException("An exception happened in constructor of "
                    + modelClass, e.getCause());
        }
    }

代碼集中在create方法,我們繼續(xù)研究create里是都創(chuàng)建了什么

    static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
//通過registry獲取Bundle ,此處推測registry應(yīng)該也是一個(gè)存儲數(shù)據(jù)的封裝類,此處代碼應(yīng)該是一個(gè)恢復(fù)獲取狀態(tài)的代碼
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
//創(chuàng)建ViewModel中的Handle
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//創(chuàng)建對外提供的controller
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//下面這兩段代碼等將SavedStateRegistry研究明白再看
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

上面的代碼大體就是一個(gè)SavedStateHandleController創(chuàng)建過程,涉及到SavedStateRegistry,SavedStateHandleController兩個(gè)類和controller.attachToLifecycle,tryToAddRecreator兩個(gè)方法
先研究SavedStateRegistry
在SavedStateViewModelFactory發(fā)現(xiàn)SavedStateRegistry是SavedStateViewModelFactory構(gòu)造函數(shù)在SavedStateRegistryOwner中獲取的,SavedStateRegistryOwner是在CommponentActivity中實(shí)現(xiàn)的,主要是一個(gè)getSavedStateRegistry的實(shí)現(xiàn)
而getSavedStateRegistry方法設(shè)計(jì)到mSavedStateRegistryController變量。。。
mSavedStateRegistryController變量在類成員變量中初始化,代碼如下

ComponentActivity
    final SavedStateRegistryController mSavedStateRegistryController =
            SavedStateRegistryController.create(this);

SavedStateRegistryController的代碼如下,

public final class SavedStateRegistryController {
    private final SavedStateRegistryOwner mOwner;
    private final SavedStateRegistry mRegistry;
//在構(gòu)造函數(shù)傳入一個(gè)Lifecycle的Owner
    private SavedStateRegistryController(SavedStateRegistryOwner owner) {
        mOwner = owner;
//這個(gè)玩意整體看了下,應(yīng)該是真正零時(shí)緩存數(shù)據(jù)的操作類(google 你來解釋下為啥要套的這么深?沒有更好的方案了嗎?)
        mRegistry = new SavedStateRegistry();
    }

  //提供對外使用的操作存儲類
    @NonNull
    public SavedStateRegistry getSavedStateRegistry() {
        return mRegistry;
    }

//這里是核心代碼,一行一行注釋,主要是數(shù)據(jù)使用前封裝
//這里主要是將恢復(fù)后的數(shù)據(jù)拿到,而且通過lifecycle將獲取時(shí)機(jī)控制在onCreate中
    @MainThread
    public void performRestore(@Nullable Bundle savedState) {
//此處拿到在ComponentActivity實(shí)例的SavedStateRegistryOwner
        Lifecycle lifecycle = mOwner.getLifecycle();
//如果Lifecycle.State的狀態(tài)在OnCreate之前會回調(diào)到這里,說明是有問題的,拋出異常
        if (lifecycle.getCurrentState() != Lifecycle.State.INITIALIZED) {
            throw new IllegalStateException("Restarter must be created only during "
                    + "owner's initialization stage");
        }
//這里做個(gè)一個(gè)一次性事件的添加,為啥是一次性?Recreator里面會解答
        lifecycle.addObserver(new Recreator(mOwner));
//將savedState里的Bundle讀出來,下面會分析
        mRegistry.performRestore(lifecycle, savedState);
    }

//數(shù)據(jù)保存前封裝 outBundle就是onSaveInstanceState中的Bundle
    @MainThread
    public void performSave(@NonNull Bundle outBundle) {
        mRegistry.performSave(outBundle);
    }

    //提供快捷創(chuàng)建函數(shù)
    @NonNull
    public static SavedStateRegistryController create(@NonNull SavedStateRegistryOwner owner) {
        return new SavedStateRegistryController(owner);
    }
}

上面這段代碼主要有三個(gè)工作內(nèi)容
1,將ComponentActivity的lifeCycle拿到
2,在創(chuàng)建真正的讀取保存類SavedStateRegistry
3,控制將恢復(fù)數(shù)據(jù)的時(shí)機(jī)控制在onCreate,并封裝SavedStateRegistry

最后看SavedStateRegistry幾個(gè)關(guān)鍵代碼


//這里savedState 是ComponentActivity里onCreate中的savedInstanceState 通過mSavedStateRegistryController.performRestore傳入
   @MainThread
    void performRestore(@NonNull Lifecycle lifecycle, @Nullable Bundle savedState) {
        if (mRestored) {
            throw new IllegalStateException("SavedStateRegistry was already restored.");
        }
//這里獲取到恢復(fù)的savedState里面的數(shù)據(jù)在 performSave 中可以看到格式
        if (savedState != null) {
//此處的mRestoredState在SavedStateHandleController中的 registry.consumeRestoredStateForKey會用到
            mRestoredState = savedState.getBundle(SAVED_COMPONENTS_KEY);
        }
//做了一個(gè)監(jiān)聽,如果執(zhí)行了Lifecycle.Event.ON_STOP 的話,記錄mAllowingSavingState,用來判斷是否是正常流程
        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;
                }
            }
        });
//做了一個(gè)是否恢復(fù)的標(biāo)記,
        mRestored = true;
    }
這里是當(dāng)onSaveInstanceState執(zhí)行時(shí),執(zhí)行的代碼
 @MainThread
    void performSave(@NonNull Bundle outBundle) {
//將內(nèi)存中的數(shù)據(jù)全部裝進(jìn)來
        Bundle components = new Bundle();
        if (mRestoredState != null) {
            components.putAll(mRestoredState);
        }
//遍歷各個(gè)生成的handle,保存handle中的數(shù)據(jù),后面看handler源碼就會發(fā)現(xiàn)每個(gè)handle都會保存一個(gè)SavedStateProvider
        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);
    }

上面代碼主要做了一個(gè)數(shù)據(jù)讀取和保存,和我們平時(shí)寫普通的數(shù)據(jù)零時(shí)保存一樣,只是做了封裝,mRestoredState作為存儲和讀取的所有數(shù)據(jù)的全局變量
最后看下ComponentActivity

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
       //代碼不多,沒做代碼省略,這句話執(zhí)行后,相當(dāng)于就是從恢復(fù)中拿到了數(shù)據(jù)
        mSavedStateRegistryController.performRestore(savedInstanceState);
        mContextAwareHelper.dispatchOnContextAvailable(this);
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
        if (mContentLayoutId != 0) {
            setContentView(mContentLayoutId);
        }
    }
  @CallSuper
    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        Lifecycle lifecycle = getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).setCurrentState(Lifecycle.State.CREATED);
        }
        super.onSaveInstanceState(outState);
//這句話執(zhí)行后,將數(shù)據(jù)零時(shí)存儲在恢復(fù)區(qū)
        mSavedStateRegistryController.performSave(outState);
    }

所以通過以上代碼的閱讀,我們已經(jīng)發(fā)現(xiàn),SavedStateHandle的核心邏輯就是通過onSaveInstanceState做臨時(shí)存儲,數(shù)據(jù)恢復(fù)只是封裝了兩層,做了很多邏輯判斷
SavedStateRegistryController->SavedStateRegistry->執(zhí)行恢復(fù)存儲。
再回到SavedStateHandleController

static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
//這行代碼,下面會簡單看下,主要是為了去哪在系統(tǒng)恢復(fù)Activity時(shí),通過getIntent中的內(nèi)容
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
//這里創(chuàng)建Handle核心代碼
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//創(chuàng)建controller 主要是綁定registry數(shù)據(jù)和handle中mSavedStateProvider的關(guān)系
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

先簡單看下consumeRestoredStateForKey中的東西

    @MainThread
    @Nullable
    public Bundle consumeRestoredStateForKey(@NonNull String key) {
        if (!mRestored) {
            throw new IllegalStateException("You can consumeRestoredStateForKey "
                    + "only after super.onCreate of corresponding component");
        }
        if (mRestoredState != null) {
            Bundle result = mRestoredState.getBundle(key);
            mRestoredState.remove(key);
            if (mRestoredState.isEmpty()) {
                mRestoredState = null;
            }
            return result;
        }
        return null;
    }

代碼很簡單,主要是通過ViewModel唯一關(guān)鍵字獲取mRestoredState里存儲的Bundle,而這個(gè)mRestoredState我們前面代碼已經(jīng)知道就是用來做activity銷毀前存儲和activtiy恢復(fù)時(shí)讀取的Bundle,所以這里相當(dāng)于通過Viewmodle的Key獲取在ViewModel中臨時(shí)存儲的數(shù)據(jù)
再看createHandle的代碼


    static SavedStateHandle createHandle(@Nullable Bundle restoredState,
            @Nullable Bundle defaultState) {
//如果沒有需要緩存或者恢復(fù)的數(shù)據(jù),直接創(chuàng)建SavedStateHandle
        if (restoredState == null && defaultState == null) {
            return new SavedStateHandle();
        }
        Map<String, Object> state = new HashMap<>();
        if (defaultState != null) {
            for (String key : defaultState.keySet()) {
                state.put(key, defaultState.get(key));
            }
        }
//如果有需要緩存的數(shù)據(jù)創(chuàng)建且沒有恢復(fù)數(shù)據(jù)的情況,一個(gè)帶緩存數(shù)據(jù)的SavedStateHandle

        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));
        }
//如果兩個(gè)都有,那就兩個(gè)都塞進(jìn)去
        return new SavedStateHandle(state);
    }

這里需要看下handle把數(shù)據(jù)存到哪里了,在構(gòu)造函數(shù)中


    /**
     * Creates a handle with the given initial arguments.
     */
    public SavedStateHandle(@NonNull Map<String, Object> initialState) {
        mRegular = new HashMap<>(initialState);
    }

    /**
     * Creates a handle with the empty state.
     */
    public SavedStateHandle() {
        mRegular = new HashMap<>();
    }

我們發(fā)現(xiàn)剛剛的數(shù)據(jù)全部塞到mRegular中了
這個(gè)mRegular就是一個(gè)Map,并且提供給外部使用


    /**
     * Returns a value associated with the given key.
     */
    @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
    @MainThread
    @Nullable
    public <T> T get(@NonNull String key) {
        return (T) mRegular.get(key);
    }

    /**
     * Associate the given value with the key. The value must have a type that could be stored in
     * {@link android.os.Bundle}
     *
     * @param <T> any type that can be accepted by Bundle.
     */
    @MainThread
    public <T> void set(@NonNull String key, @Nullable T value) {
        validateValue(value);
        @SuppressWarnings("unchecked")
        MutableLiveData<T> mutableLiveData = (MutableLiveData<T>) mLiveDatas.get(key);
        if (mutableLiveData != null) {
            // it will set value;
            mutableLiveData.setValue(value);
        } else {
            mRegular.put(key, value);
        }
    }

也就是說handle主要是提供了一個(gè)mRegular的Map提供業(yè)務(wù)層讀取和存儲(甚至提供了一個(gè)LiveData,這里就不展開了),但是真實(shí)存儲的時(shí)候,我們發(fā)現(xiàn)是下面這段代碼(上面已經(jīng)閱讀過,需要重新看下)

 @MainThread
    void performSave(@NonNull Bundle outBundle) {
...
        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);
    }

這里發(fā)現(xiàn)是遍歷的mComponents中的SavedStateProvider,執(zhí)行的saveState方法,在Handle中也存在這樣一段代碼

    private final SavedStateProvider mSavedStateProvider = new SavedStateProvider() {
        @SuppressWarnings("unchecked")
        @NonNull
        @Override
        public Bundle saveState() {
            // Get the saved state from each SavedStateProvider registered with this
            // SavedStateHandle, iterating through a copy to avoid re-entrance
            Map<String, SavedStateProvider> map = new HashMap<>(mSavedStateProviders);
            for (Map.Entry<String, SavedStateProvider> entry : map.entrySet()) {
                Bundle savedState = entry.getValue().saveState();
                set(entry.getKey(), savedState);
            }
            // Convert the Map of current values into a Bundle
            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;
        }
    };

上面的代碼沒有寫注釋,大體意思就是把mRegular中的數(shù)據(jù)塞到Bundle里,我們可以聯(lián)想,應(yīng)該是在performSave時(shí),調(diào)用handle中的SavedStateProvider里的saveState方法獲取Bundle并保存的,那就是handle中的SavedStateProvider會存到SavedStateRegistry的mComponents中。。但是在哪塞入的呢?我們再回到SavedStateHandleController中看下一個(gè)方法

  static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
            String key, Bundle defaultArgs) {
        Bundle restoredState = registry.consumeRestoredStateForKey(key);
        SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
        SavedStateHandleController controller = new SavedStateHandleController(key, handle);
//目前只有下面這兩句可能會將handle里的SavedStateProvider和SavedStateRegistry里的mComponents做數(shù)據(jù)綁定了
        controller.attachToLifecycle(registry, lifecycle);
        tryToAddRecreator(registry, lifecycle);
        return controller;
    }

先看attachToLifecycle

    void attachToLifecycle(SavedStateRegistry registry, Lifecycle lifecycle) {
        if (mIsAttached) {
            throw new IllegalStateException("Already attached to lifecycleOwner");
        }
        mIsAttached = true;
        lifecycle.addObserver(this);
//這句話明顯感覺就是用來綁定數(shù)據(jù)的
        registry.registerSavedStateProvider(mKey, mHandle.savedStateProvider());
    }

再看registerSavedStateProvider

    @MainThread
    public void registerSavedStateProvider(@NonNull String key,
            @NonNull SavedStateProvider provider) {
//這里果然做了數(shù)據(jù)put
        SavedStateProvider previous = mComponents.putIfAbsent(key, provider);
        if (previous != null) {
            throw new IllegalArgumentException("SavedStateProvider with the given key is"
                    + " already registered");
        }
    }

SafeIterableMap mComponents

    public V putIfAbsent(@NonNull K key, @NonNull V v) {
        Entry<K, V> entry = get(key);
        if (entry != null) {
            return entry.mValue;
        }
        put(key, v);
        return null;
    }

看過最后這塊代碼,我們整個(gè)Handle的邏輯就很清晰了,下面說下文字流程

1在通過SavedStateViewModelFactory創(chuàng)建ViewModel時(shí),先通過構(gòu)造函數(shù)入?yún)⑴袛嗍欠翊嬖赟avedStateHandle入?yún)?,如果存在就?zhí)行創(chuàng)建SavedStateHandleController
2通過SavedStateHandleController.create創(chuàng)建SavedStateHandleController,在創(chuàng)建SavedStateHandleController時(shí)將Activtiy中實(shí)現(xiàn)的SavedStateRegistryOwner通過getSavedStateRegistry傳入mSavedStateRegistry
3mSavedStateRegistry在ComponentActivity通過SavedStateRegistryController.create()實(shí)例,并且在ComponentActivity中onCreate里執(zhí)行了performRestore方法,在onSaveInstanceState里執(zhí)行了performSave方法
4在SavedStateHandleController創(chuàng)建時(shí),先獲取mSavedStateRegistry在ComponentActivity里的onCreate是獲取到的數(shù)據(jù),并且將數(shù)據(jù)塞到創(chuàng)建的SavedStateHandle中的mRegular里
5再將SavedStateHandle封裝到 SavedStateHandleController中,并將handel里的mSavedStateProvider塞到mSavedStateRegistry中的mComponents中
6當(dāng)Activity被系統(tǒng)殺死時(shí),執(zhí)行onSaveInstanceState,觸發(fā)mSavedStateRegistry.performSave
7在performSave時(shí),遍歷mComponents,執(zhí)行mSavedStateProvider的saveState封裝數(shù)據(jù),塞到onSaveInstanceState的Bundle里

最后上自己畫的handle代碼簡易邏輯圖


handle代碼簡易邏輯圖
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容