读完这篇文章,你会知道什么?
- 为什么
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
: 需求完成onStateChanged
DefaultLifecycleObserver
:需求完成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
相关成员
SavedStateRegistryController
SavedStateRegistry
SavedStateRegistryOwner
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
存储和康复机制的;