ViewModel 類被設(shè)計用來管理 UI 相關(guān)數(shù)據(jù)奠旺,持有一個或多個 LiveData施流。
它的特性:生命周期不隨系統(tǒng)配置改變的影響嫂沉,組件被進程殺掉后,支持?jǐn)?shù)據(jù)恢復(fù)趟章。
ViewModel 創(chuàng)建流程
基本流程:ViewModelProvider 類的 get() 方法,首先赖淤,根據(jù) key 谅河,從 ViewModelStore 中查找,如果不存在吐限,利用內(nèi)部 ViewModelProvider.Factory 工廠創(chuàng)建褂始,并存入 ViewModelStore。
ViewModelStore 存儲類是為了 ViewModel 的生命周期保持狐粱。工廠可配置胆数,系統(tǒng)默認(rèn)提供幾種工廠。
ViewModelProvider 的構(gòu)造方法有組件 Owner 參數(shù)蒋搜,如下胰伍。
public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory
? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()
: NewInstanceFactory.getInstance());
}
如果組件同時實現(xiàn)以上接口酸休,(例ComponentActivity) 斑司,從組件中拿 ViewModelStore 和 Factory ,ComponentActivity 內(nèi)部默認(rèn)工廠是 SavedStateViewModelFactory宿刮,它創(chuàng)建的 ViewModel 支持?jǐn)?shù)據(jù)恢復(fù)僵缺。
ViewModel 創(chuàng)建時,不會傳入 Context 磕潮,如果需要 Context ,創(chuàng)建 AndroidViewModel 之景。
配置改變的生命周期保持
系統(tǒng)配置改變時流程
onRetainNonConfigurationInstance() 方法锻狗,在 ActivityThread類 performDestoryActivity() 觸發(fā),此時油额,已經(jīng)執(zhí)行過 onSaveInstanceState()桐磁,還未執(zhí)行onDestory()。
該方法用于將組件中的 ViewModelStore 對象衬以,保存在NonConfigurationInstances校摩,返回該 NonConfigurationInstances,即保存狀態(tài)互妓。
系統(tǒng)組件重建時坤塞,在 onCreate()方法,會通過 getViewModelStore() 構(gòu)建 內(nèi)部 ViewModelStore 對象灼狰,優(yōu)先 getLastNonConfigurationInstance() 方法 恢復(fù)原有狀態(tài) (同一個對象)浮禾,從NonConfigurationInstances中獲取ViewModelStore。
因此蝴簇,在配置改變時匆帚,ViewModel 對象是不變的。
只有當(dāng)組件真正結(jié)束時荡澎,ViewModel 的生命周期才會結(jié)束,由系統(tǒng)執(zhí)行 onClear() 方法彤委。
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
這是 ComponentActivity 基類組件 構(gòu)造方法中注冊的一個生命周期Observer或衡,當(dāng)組件銷毀時焦影,檢測是否因 Configuration 改變導(dǎo)致銷毀,主動銷毀才會通過 ViewModelStore 清理ViewModel封断, onClear() 方法斯辰。
總結(jié):組件利用 onRetainNonConfigurationInstance() 和 getLastNonConfigurationInstance() ,實現(xiàn)組件內(nèi)部 ViewModelStore存儲器 的 保存和恢復(fù)坡疼。
屏幕旋轉(zhuǎn)彬呻,可以通過恢復(fù)的 ViewModelStore 獲取 ViewModel ,其數(shù)據(jù)是不需要重新獲取柄瑰。
組件被系統(tǒng)回收時 ViewModel 數(shù)據(jù)恢復(fù)
本質(zhì)是利用 onCreate() 和 onSaveInstanceState() 方法闸氮。
支持需要工廠類創(chuàng)建 ViewModel 時,構(gòu)造方法參數(shù)包含SavedStateHandle教沾,如 SavedStateViewModelFactory 工廠、或抽象 AbstractSavedStateViewModelFactory 工廠授翻。
該類本身是一Map數(shù)據(jù)或悲,內(nèi)部一個SavedStateProvider,將Map數(shù)據(jù)→Bundle堪唐。
自動注冊到SavedStateRegistry巡语。
兩種場景:
1,組件恢復(fù)數(shù)據(jù)時淮菠,在 onCreate() 方法男公,讀取 Bundle ,通過內(nèi)部控制器 SavedStateRegistryController 委派給 SavedStateRegistry兜材。
將 Bundle mRestoredState 保存在 SavedStateRegistry理澎。
ViewModel 創(chuàng)建時逞力,消費掉該 Bundle曙寡,轉(zhuǎn)存入 SavedStateHandle 的 Map 。
2寇荧,組件回收時举庶,基礎(chǔ)組件 ComponentActivity 的 onSaveInstanceState() 方法,通過內(nèi)部控制器 SavedStateRegistryController 委派給 SavedStateRegistry揩抡。
基于此前 SavedStateRegistry < == > SavedStateProvider 建立的關(guān)系户侥,由 SavedStateProvider 負(fù)責(zé)搜集 SavedStateHandle 中的 Map 數(shù)據(jù) 交給Bundle镀琉。
總結(jié):系統(tǒng)回收組件時,ViewModel 對象會重新創(chuàng)建蕊唐,數(shù)據(jù)可恢復(fù)屋摔。
任重而道遠(yuǎn)