读完这篇文章,你会知道什么?
- 为什么
ViewModel#onClear履行在Activity#onDestory之前,但生命周期比Activity长 -
LifecycleObserver是怎样兼容LifecycleEventObserver和DefaultLifecycleObserver -
SavedStateRegistry作业机制和触及每个类的责任 -
ViewModel创立进程中触及每个类的责任 -
SavedStateHandle效果及两种创立进程的差异 -
rememberSaveable状况存储进程中触及每个类的责任 -
Compose NavHost是怎样自定义LifecycleOwner、ViewModelStoreOwner、SavedStateRegistryOwner、SaveableStateRegistry
Lifecycle 组件
相关成员
-
LifecycleOwner:Lifecycle的所有者,用于供给Lifecycle -
LifecycleRegistry:Lifecycle的子类,能够直接运用然后快速自定义生命周期办理和监听分发 -
LifecycleObserver: 生命周期观察者, 用于监听生命周期的改变,默许子类有LifecycleEventObserver和DefaultLifecycleObserver
- Tips:
ComponentActivity运用ReportFragment调用LifecycleRegistry分发本身生命周期
疑问:
-
ViewModel#onClear的履行是在Activity#preDestory的时分调用,为什么说ViewModel的生命周期比Activity长
- 在
ViewModel#onClear履行的时分,会判别是否由于装备改变导致的Activity销毁,假如不是则履行ViewModel#onClear;假如是的话,则不履行ViewModel的整理作业- 在因装备修正导致
Activity重启的时分,会存储当时ComponentActivity#ViewModelStore到ActivityThread#ActivityClientRecord#lastNonConfigurationInstances上
- 调用链:
ActivityThread#performDestroyActivity->Activity#retainNonConfigurationInstances->ComponentActivity#onRetainNonConfigurationInstance- 在
ComponentActivity#onRetainNonConfigurationInstance办法可知,ComponentActivity子类可重写onRetainCustomNonConfigurationInstance办法来持有 不因装备修正的状况;不过已经被抛弃,运用ViewModel来存储 不因装备修正的状况
- 在因装备改变重启
原Activity的时分,ActivityThread#performLaunchActivity会调用activity#attch一起会带着前次保存的Activity#NonConfigurationInstances状况- 在
ComponentActivity#getViewModelStore中,会先Activity#NonConfigurationInstances#activity字段获取到ComponentActivity#NonConfigurationInstances#viewModelStore,然后康复重启之前的ViewModel数据相关类
// Activity static final class NonConfigurationInstances { Object activity; // 一般为ComponentActivity#NonConfigurationInstances HashMap<String, Object> children; FragmentManagerNonConfig fragments; ArrayMap<String, LoaderManager> loaders; VoiceInteractor voiceInteractor; }// ComponentActivity下 static final class NonConfigurationInstances { // 能够重写 ComponentActivity#onRetainCustomNonConfigurationInstance 注入 Object custom; // 存储了ComponentActivity#ViewModelStore ViewModelStore viewModelStore; }
- 为什么
LifecycleObserver没有任何办法定义
LifecycleObserver没有任何完成,是由于原先运用办法是自定义办法加上对应生命周期注解运用的,在androidx.lifecycle-*:2.4.0被抛弃了,所以是没有任何办法定义class CustomLifecycleObserver : LifecycleObserver { @@OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun onStop() { // ... } }
- 体系是怎样完成注入
LifecycleEventObserver或者DefaultLifecycleObserver都能够正常收取对应到回调
LifecycleEventObserver: 需求完成onStateChangedDefaultLifecycleObserver:需求完成onCreate、onStart、onResume、onPause、onStop、onDestory- 经过
LifecycleRegistry#addObserver可知,传入的observer会经过Lifecycling.lifecycleEventObserver最终仍是转换为LifecycleEventObserver; 能够看到本质仍是经过LifecycleEventObserver的办法转换调用DefaultLifecycleObserver的onCreate等办法- 一起由
FullLifecycleObserverAdapter可知, 假如Observer一起完成LifecycleEventObserver和DefaultLifecycleObserver都会调用对应的回调
- 生命周期是
跳动式的仍是递进式
- 由
LifecycleRegistry的backwardPass和forwardPass可知,状况是一级一级的递进,而不是突然跳动
SavedStateRegistryOwner
-
androidX依据Activity的onSaveInstanceState和onCreate封装的一套API,能够在需求存储数据的时分履行SavedStateRegistry#performSave,在需求康复数据的时分履行SavedStateRegistry#performRestore; - 其中存储的数据需求支持序列化
Parcelable
相关成员
SavedStateRegistryControllerSavedStateRegistrySavedStateRegistryOwner
SavedStateRegistryController 责任
-
performAttch: 注入Recreator和履行SavedStateRegistry#performAttch -
performRestore调用SavedStateRegistry#performRestore -
performSave调用SavedStateRegistry#performSave
Recreator 责任
- 用于保存
SavedStateRegistry#AutoRecreated的调集 - 在康复的时分,主动创立和调用
SavedStateRegistry#AutoRecreated的调集
SavedStateRegistry 责任
-
SavedStateProvider用于供给怎样保存状况的接口 - 在
SavedStateRegistry被重启的时分,会主动创立已加入AutoRecreated调集相关的类; 经过SavedStateRegistry#runOnNextRecreation增加到主动创立列表中 - 存储和康复相关办法:
performSave(保存存储状况) 和performRestore(获得存储状况) - 经过
registerSavedStateProvider和unregisterSavedStateProvider键值对办法办理SavedStateProvider - 经过
consumeRestoredStateForKey获取 存储的状况信息
ComponentActivity 与 SavedStateRegistry 交互代码
public class ComponentActivity {
// ..
public ComponentActivity() {
// ...
mSavedStateRegistryController.performAttach(); // 关联
// ..
}
// ..
protected void onCreate(@Nullable Bundle savedInstanceState) {
// ...
// 康复数据到 SavedStateRegistry
mSavedStateRegistryController.performRestore(savedInstanceState);
// ..
}
protected void onSaveInstanceState(@NonNull Bundle outState) {
// ..
// 存储当时状况 - 每次 onPause 事件发生的时分履行
mSavedStateRegistryController.performSave(outState);
}
}
疑问:
- 为什么不运用
onSaveInstanceState对应的onRestoreInstanceState来履行康复,而运用 onCreate?
猜想:
onRestoreInstanceState在framework在第一次分发onStart的时分履行;
onSaveInstanceState在framework每次分发onPause的时分履行保存状况;
在onCreate履行康复, 猜想是为了更早的康复,源码内置了挺多依据生命周期onCreate消费康复数据的
- Tips: 其中状况都是从
ActivityClientRecord#state上获取
SavedStateHandle – ViewModel 的状况存储和康复东西
-
SavedStateHandle最终也是挂载SavedStateRegistry上完成状况存储和康复的,所以也是需求存储的内容是能够被序列化的
ViewModel 创立的相关类
-
ViewModelStore: 用于寄存ViewModel实例 -
ViewModelProvider.Factory: 负责怎样创立ViewModel实例 -
ViewModelProvider: 负责控制ViewModelStore和ViewModelProvider.Factory的履行流程 -
CreationExtra: 能够带着ViewModel创立参数,需求与ViewModelProvider.Factory合作运用 -
HasDefaultViewModelProviderFactory: 在运用ViewModelStoreOwner创立ViewModelProvider的时分,假如当时owner归于HasDefaultViewModelProviderFactory完成,则会从中提取默许的ViewModelProvider.Factory和CreationExtra;
- 由于
androidx.activity.ComponentActivity完成HasDefaultViewModelProviderFactory,所以运用ViewModelProvider(this)是能够创立出带SavedStateHandle的ViewModel - 其实能从
ComponentActivity#getDefaultViewModelCreationExtras的完成可知,依据键值对的办法注入了一些常用参数
// androidx.activity.ComponentActivity 的完成
public CreationExtras getDefaultViewModelCreationExtras() {
MutableCreationExtras extras = new MutableCreationExtras();
if (getApplication() != null) {
extras.set(ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY, getApplication());
}
extras.set(SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY, this);
extras.set(SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY, this);
if (getIntent() != null && getIntent().getExtras() != null) {
extras.set(SavedStateHandleSupport.DEFAULT_ARGS_KEY, getIntent().getExtras());
}
return extras;
}
SavedStateHandle
- 由
AbstractSavedStateViewModelFactory源码可知,SavedStateHandle有2种创立办法
-
SavedStateHandleSupport#createSavedStateHandle创立办法;会创立一个SavedStateHandlesProvider专门办理SavedStateHandle存储和康复,一起在创立SavedStateHandlesProvider的时分会主动挂载SavedStateRegistry身上和装载康复的数据
// 在结构函数的时分的时分调用, 创立 SavedStateHandlesProvider
fun <T> T.enableSavedStateHandles()
where T : SavedStateRegistryOwner, T : ViewModelStoreOwner {
val currentState = lifecycle.currentState
require(
currentState == Lifecycle.State.INITIALIZED || currentState == Lifecycle.State.CREATED
)
if (savedStateRegistry.getSavedStateProvider(SAVED_STATE_KEY) == null) {
val provider = SavedStateHandlesProvider(savedStateRegistry, this)
// 将 SavedStateHandlesProvider 注册到 savedStateRegistry
savedStateRegistry.registerSavedStateProvider(SAVED_STATE_KEY, provider)
lifecycle.addObserver(SavedStateHandleAttacher(provider))
}
}
internal class SavedStateHandleAttacher(
private val provider: SavedStateHandlesProvider
) : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
check(event == Lifecycle.Event.ON_CREATE) {
"Next event must be ON_CREATE, it was $event"
}
source.lifecycle.removeObserver(this)
// 康复数据
provider.performRestore()
}
}
- 由
LegacySavedStateHandleController办法创立,由对应的ViewModel持有Controller, 此Controller主要是用于挂载SavedStateRegistry和装载康复数据
- Tips:由于
ViewModel持有LegacySavedStateHandleController, 所以在界面装备修正,会进行界面重启;但此时ViewModel已经生成,所以内部完成了SavedStateRegistry.AutoRecreated用于在这种状况将SavedStateHandle从头挂载到SavedStateRegistry上
疑问
- 默许
ViewModel#key怎样决议的
默许由
ViewModelProvider#get办法决议, 值为androidx.lifecycle.ViewModelProvider.DefaultKey:${modelClass.canonicalName}, 也能够调用双参数的办法进行自定义key传入
-
SavedStateHandle#savedStateProvider在savedStateRegistry中的注册的key是什么
是运用
ViewModel#key注册的,在默许状况下,重启康复key也不会发生改变,然后能够正确康复状况
-
ViewModel和SavedStateHandle的关系
ViewModel和SavedStateHandle是1对1的关系;默许是运用ViewModel#key在savedStateRegistry注册SavedStateProvider用于保存数据和康复数据的
- 2种创立
SavedStateHandle有什么差异
- 关于运用方来说, 2种创立得到
SavedStateHandle运用办法是完全一致的;- 我翻了一下 ViewModel-SavedState 库的历史记录,发现
LegacySavedStateHandleController是最开始创立SavedStateHandle的一套;- 而经过
CreationExtras.createSavedStateHandle创立SavedStateHandle是中途新加入的一种创立办法;- 二种办法共存
应该是兼容新老版本的交替运用
SaveableStateRegistry(Compose的状况存储)
DisposableSaveableStateRegistry 责任
- 挂载到
Android Lifecycle SavedStateRegistry上,调用SaveableStateRegistry#performSave存储和 带康复数据创立SaveableStateRegistry - 扩展
SaveableStateRegistry功用,增加onDispose办法,取消Android Lifecycle SavedStateRegistry注册
SaveableStateRegistry 责任
-
canBeSaved: (Any) -> Boolean: 判别检查存储目标是否合法 -
consumeRestored: 耗费康复数据 -
registerProvider+Entry: 注册和反注册存储回调,一次注册[key] -> [() -> Any?] -
performSave: 存储当时已注册的Provider和 已康复未耗费的数据
rememberSaveable 责任
- 履行
SaveableStateRegistry#consumeRestored耗费缓存数据 - 进入的时分调用
SaveableStateRegistry注册,在离开界面的时分进行SaveableStateRegistry反注册
Saver 责任
- 用于从
SaveableStateRegistry康复的数据转换成 业务数据 - 用于 业务数据 转成可被
SaveableStateRegistry康复存储的 数据
- Tips: 存储的时分带着
SaverScope是能够用来调用SaveableStateRegistry#canBeSaved,判别目标是否能够被保存 -
Saver相关衍生目标有三个:
-
listSaver: 把 目标 拆分红list, 然后把list转换成 目标 -
autoSaver:saver的默许完成,不会做任何转换 -
mapSaver: 把 目标 拆分红map, 然后把map转换成 目标,底层运用listSaver完成
疑问
- 康复是指定
key对应一个List<Any?>, 但注册是一个key对应一个() -> Any?
答: 在
Composable或许会一起取相同的key,依照先后顺序,能够确认所需求的方位,由于只有rememberSaveable能消费,除非开发者自定义导致异常,否则一般不会出现问题
Composable – NavHost 自定义 owner
自定义 NavBackStackEntry#LifecycleOwner
- 当时生命周期 = Math.min(外部生命周期, 内部生命周期)
-
外部生命周期 监听外部
Lifecyle可得 -
内部生命周期 由
NavController分发可得
自定义 NavBackStackEntry#ViewModelStoreOwner
- 运用外部
ViewModelStore创立一个NavControllerViewModel,key为androidx.lifecycle.ViewModelProvider.DefaultKey:${modelClass.canonicalName},则ViewModelStore不变的状况先,每次获取的NavControllerViewModel为同一个 - 在创立
NavBackStackEntry的时分,会传入NavControllerViewModel实例 - 获取
NavBackStackEntry#viewModelStore的时分,会从NavControllerViewModel加上本身NavBackStackEntry#id[UUID]获取到对应ViewModelStore,UUID不变则获取的ViewModelStore也不变
- Tips:
NavControllerViewModel本身便是ViewModel也是NavViewModelStoreProvider, 用于供给ViewModelStore和办理已供给的ViewModelStore
自定义 NavBackStackEntry#SavedStateRegistryOwner
- 在
NavBackStackEntry履行初次更新生命周期的时分履行savedStateRegistryController#performAttach和savedStateRegistryController#performRestore用于挂载和康复savedStateRegistry - 在每次
NavBackStackEntry存储状况的时分,会调用本身NavBackStackEntry#saveState用于存储本身SavedStateRegistry状况
自定义 NavBackStackEntry#SaveableStateRegistry
- 运用
rememberSaveableStateHolder创立SaveableStateHolder,一起SaveableStateHolder#parentSaveableStateRegistry会赋值为LocalSaveableStateRegistry.current - 利用
NavBackStackEntry#ViewModelStoreOwner创立一个BackStackEntryIdViewModel, 用于供给 仅有id、 onCleared 办法移除当时状况、弱引证SaveableStateHolder - 运用 仅有id 和 子Composable 生成一个
RegistryHolder, 用于控制内部SaveableStateRegistry的存储和数据康复 - 运用
RegistryHolder#registry为 子Composable 供给新的LocalSaveableStateRegistry的环境 -
DisposableEffect#进入组合移除状况(已康复了) 和 增加RegistryHolder,DisposableEffect#onDispose存储状况 和 移除RegistryHodler
疑问
-
ViewModel#onClear和DisposableEffect都有做清除操作,区别是什么
答:
SaveableStateHolder的生命周期是附归于父的SaveableStateRegistry;ViewModel#onClear是界面退出的时分调用,所以从弱引证获取saveableStateHolderRef移除本身状况,不用在保存和康复;而DisposbaleEffect是每次进入组合都会履行,所以在进入组合的时分提取状况,退出组合保存状况;
自定义 SavedStateHandle: 或许是用于 NavBackStackEntry 本身数据存储和康复
- 从
NavResultSavedStateFactory和NavBackStackEntry#ViewModelStore生成SavedStateViewModel - 从
SavedStateViewModel获取handle
NavHost
- 获取当时
LifecycleOwner, 设置LifecycleObserver, 用于分发当时生命周期到NavController#backQueue - 设置当时
ViewModelStore, 生成一个NavControllerViewModel - 运用当时
NavBackStackEntry为子Composable供给LifecycleOwner、ViewModelStoreOwner、SavedStateRegistryOwner环境, 运用创立的SaveableStateHandler供给SaveableStateRegistry
- Tips:
SaveableStateHandler是存储在SaveableStateRegistry,并供给SaveableStateRegistry - Tips:
NavControllerViewModel运用父环境的ViewModelStore存储,依据BackStackEntry#id生成对应的ViewModelStore - Tips:
NavBackStackEntry完成SavedStateRegistry, 能够康复和存储数据
总结
从 ViewModel#SavedStateHandle 和 Compose#SaveableStateRegistry 来看,可见状况存储和康复本质仍是依托 SavedStateRegistry, 而 SavedStateRegistry 又是依托 Activity 本身的 onSaveInstanceState 存储和康复机制的;
