前言
閱讀本篇文章前最好先看上篇文章ViewModel源碼閱讀(一)ViewModel的生命周期
在閱讀SavedStateHandle之前钧椰,我們需要搞清上篇文章通過getLastNonConfigurationInstance和onRetainNonConfigurationInstance存儲的數(shù)據(jù)叠纷,與通過onSaveInstanceState和Bundle存儲的數(shù)據(jù)有什么不同
我這里直接就說出結(jié)論了
getLastNonConfigurationInstance是通過NonConfigurationInstances保存狀態(tài)的孵睬,這個狀態(tài)可以獲取的前提是進程沒有被銷毀
onSaveInstanceState中Bundle是通過Parcel保存狀態(tài)的,這種保存的狀態(tài)是非依附于進程的,當前進程被殺死,狀態(tài)也是保留的
詳細可以參考這篇文章,這里就不展開討論了
在上面邏輯基礎(chǔ)上,和上篇文章分析的ViewModel生命周期摊腋,我們可以推測出,ViewModel在進程被系統(tǒng)殺死時嘁傀,再恢復(fù)時兴蒸,是重新創(chuàng)建實例的,所以ViewModel引入了SavedStateHandle细办,來做輕量數(shù)據(jù)狀態(tài)暫存
分析代碼
這塊的代碼我第一次看的時候有點繞橙凳,因為關(guān)聯(lián)類太多了蕾殴,所以這塊代碼單獨獨立出來
下面開始閱讀源碼
@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)鍵代碼
//此處傳入了一個mSavedStateRegistry 和mLifecycle 作用暫時未知
//key和mDefaultArgs分別對應(yīng)ViewModel的唯一標識和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)該也是一個存儲數(shù)據(jù)的封裝類坚踩,此處代碼應(yīng)該是一個恢復(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;
}
上面的代碼大體就是一個SavedStateHandleController創(chuàng)建過程荡灾,涉及到SavedStateRegistry,SavedStateHandleController兩個類和controller.attachToLifecycle瞬铸,tryToAddRecreator兩個方法
先研究SavedStateRegistry
在SavedStateViewModelFactory發(fā)現(xiàn)SavedStateRegistry是SavedStateViewModelFactory構(gòu)造函數(shù)在SavedStateRegistryOwner中獲取的批幌,SavedStateRegistryOwner是在CommponentActivity中實現(xiàn)的,主要是一個getSavedStateRegistry的實現(xiàn)
而getSavedStateRegistry方法設(shè)計到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ù)傳入一個Lifecycle的Owner
private SavedStateRegistryController(SavedStateRegistryOwner owner) {
mOwner = owner;
//這個玩意整體看了下,應(yīng)該是真正零時緩存數(shù)據(jù)的操作類(google 你來解釋下為啥要套的這么深恢着?沒有更好的方案了嗎?)
mRegistry = new SavedStateRegistry();
}
//提供對外使用的操作存儲類
@NonNull
public SavedStateRegistry getSavedStateRegistry() {
return mRegistry;
}
//這里是核心代碼财破,一行一行注釋掰派,主要是數(shù)據(jù)使用前封裝
//這里主要是將恢復(fù)后的數(shù)據(jù)拿到,而且通過lifecycle將獲取時機控制在onCreate中
@MainThread
public void performRestore(@Nullable Bundle savedState) {
//此處拿到在ComponentActivity實例的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");
}
//這里做個一個一次性事件的添加,為啥是一次性俊性?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);
}
}
上面這段代碼主要有三個工作內(nèi)容
1,將ComponentActivity的lifeCycle拿到
2定页,在創(chuàng)建真正的讀取保存類SavedStateRegistry
3趟薄,控制將恢復(fù)數(shù)據(jù)的時機控制在onCreate,并封裝SavedStateRegistry
最后看SavedStateRegistry幾個關(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);
}
//做了一個監(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;
}
}
});
//做了一個是否恢復(fù)的標記卒落,
mRestored = true;
}
這里是當onSaveInstanceState執(zhí)行時羡铲,執(zhí)行的代碼
@MainThread
void performSave(@NonNull Bundle outBundle) {
//將內(nèi)存中的數(shù)據(jù)全部裝進來
Bundle components = new Bundle();
if (mRestoredState != null) {
components.putAll(mRestoredState);
}
//遍歷各個生成的handle,保存handle中的數(shù)據(jù)儡毕,后面看handler源碼就會發(fā)現(xiàn)每個handle都會保存一個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);
}
上面代碼主要做了一個數(shù)據(jù)讀取和保存也切,和我們平時寫普通的數(shù)據(jù)零時保存一樣,只是做了封裝,mRestoredState作為存儲和讀取的所有數(shù)據(jù)的全局變量
最后看下ComponentActivity
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
//代碼不多雷恃,沒做代碼省略疆股,這句話執(zhí)行后,相當于就是從恢復(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ù)零時存儲在恢復(fù)區(qū)
mSavedStateRegistryController.performSave(outState);
}
所以通過以上代碼的閱讀押桃,我們已經(jīng)發(fā)現(xiàn),SavedStateHandle的核心邏輯就是通過onSaveInstanceState做臨時存儲导犹,數(shù)據(jù)恢復(fù)只是封裝了兩層唱凯,做了很多邏輯判斷
SavedStateRegistryController->SavedStateRegistry->執(zhí)行恢復(fù)存儲。
再回到SavedStateHandleController
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
//這行代碼谎痢,下面會簡單看下磕昼,主要是為了去哪在系統(tǒng)恢復(fù)Activity時,通過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票从,而這個mRestoredState我們前面代碼已經(jīng)知道就是用來做activity銷毀前存儲和activtiy恢復(fù)時讀取的Bundle,所以這里相當于通過Viewmodle的Key獲取在ViewModel中臨時存儲的數(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ù)的情況峰鄙,一個帶緩存數(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));
}
//如果兩個都有,那就兩個都塞進去
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中了
這個mRegular就是一個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主要是提供了一個mRegular的Map提供業(yè)務(wù)層讀取和存儲(甚至提供了一個LiveData,這里就不展開了)囊扳,但是真實存儲的時候吩翻,我們發(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時,調(diào)用handle中的SavedStateProvider里的saveState方法獲取Bundle并保存的雪侥,那就是handle中的SavedStateProvider會存到SavedStateRegistry的mComponents中球涛。。但是在哪塞入的呢校镐?我們再回到SavedStateHandleController中看下一個方法
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;
}
看過最后這塊代碼亿扁,我們整個Handle的邏輯就很清晰了,下面說下文字流程
1在通過SavedStateViewModelFactory創(chuàng)建ViewModel時鸟廓,先通過構(gòu)造函數(shù)入?yún)⑴袛嗍欠翊嬖赟avedStateHandle入?yún)⒋幼#绻嬖诰蛨?zhí)行創(chuàng)建SavedStateHandleController
2通過SavedStateHandleController.create創(chuàng)建SavedStateHandleController襟己,在創(chuàng)建SavedStateHandleController時將Activtiy中實現(xiàn)的SavedStateRegistryOwner通過getSavedStateRegistry傳入mSavedStateRegistry
3mSavedStateRegistry在ComponentActivity通過SavedStateRegistryController.create()實例,并且在ComponentActivity中onCreate里執(zhí)行了performRestore方法牍陌,在onSaveInstanceState里執(zhí)行了performSave方法
4在SavedStateHandleController創(chuàng)建時擎浴,先獲取mSavedStateRegistry在ComponentActivity里的onCreate是獲取到的數(shù)據(jù),并且將數(shù)據(jù)塞到創(chuàng)建的SavedStateHandle中的mRegular里
5再將SavedStateHandle封裝到 SavedStateHandleController中毒涧,并將handel里的mSavedStateProvider塞到mSavedStateRegistry中的mComponents中
6當Activity被系統(tǒng)殺死時贮预,執(zhí)行onSaveInstanceState,觸發(fā)mSavedStateRegistry.performSave
7在performSave時契讲,遍歷mComponents仿吞,執(zhí)行mSavedStateProvider的saveState封裝數(shù)據(jù),塞到onSaveInstanceState的Bundle里
最后上自己畫的handle代碼簡易邏輯圖