Jetpack系列:
写文章 - Lifecycle使用方法、原理分析 - 掘金 (juejin.cn)
LiveData使用方法、原理分析 - 掘金 (juejin.cn)
ViewModel使用方法、原理分析(一) - 掘金 (juejin.cn)
ViewModel使用方法、原理分析(二) - 掘金 (juejin.cn)
自定义View中获取ViewModel - 掘金 (juejin.cn)
本章节重点分析ViewModel在Activity配置发生变化时保存数据,在Android官方文档中解释ViewModel生命周期长于Activity
ViewModel 的生命周期
ViewModel对象的作用域限定为获取 ViewModel时传递给ViewModelProvider的 ViewModelStoreOwner的Lifecycle将一直留在内存中,直到其作用域ViewModelStoreOwner永久消失,ViewModels 成为了存储在配置更改后仍然存在的数据的绝佳解决方案
PS: activity 经历屏幕旋转而后结束时所处的各种生命周期状态,代码验证一下
class CustomViewModel(savedStateHandle: SavedStateHandle):ViewModel() {
var count = 1
init {
val param = savedStateHandle.get<String>("param")
Log.d("TAG", "===========param:$param")
count = 100
}
fun changeValue(){
count = 100
}
}
class CustomViewActivity:ComponentActivity() {
private val viewModel by viewModels<CustomViewModel>()
override fun onResume() {
super.onResume()
Log.d("TAG", "===========count:${viewModel.count}")
viewModel.changeValue()
}
}
=========onCreate========
=========onStart========
=========onResume========
===========viewModel:com.malaysia.myapplication.CustomViewModel@9448ba
===========count:1
=========onPause========
=========onSaveInstanceState========
=========onDestroy========
=========onCreate========
=========onStart========
=========onRestoreInstanceState========
=========onResume========
===========viewModel:com.malaysia.myapplication.CustomViewModel@9448ba
=======count:100
根据上一节CompentAcvitity实现ViewModelStoreOwner,ComponentActivity中持有mViewModelStore对象,调用父类Activity中的方法getLastNonConfigurationInstance(),注意在ComponentActivity&Activity中都存在一个静态内部类,容易造成误解,详细流程如下:
ComponentActvity获取getLastNonConfigurationInstance(),返回Activity中NonConfigurationInstances保存的activity对象,该对象指向ComponentActivity中的方法onRetainNonConfigurationInstance,返回的就是持有ViewModelStore对象的NonConfigurationInstances
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
/**
* Activity
*
**/
public class Activity extends ContextThemeWrapper {
static final class NonConfigurationInstances {
Object activity; //对应时ComponentActivity中的NonConfigurationInstances
HashMap<String, Object> children;
FragmentManagerNonConfig fragments;
ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
@Nullable
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
NonConfigurationInstances retainNonConfigurationInstances() {
//onRetainNonConfigurationInstance调用的ComponentActivity中方法
Object activity = onRetainNonConfigurationInstance();
......
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
nci.children = children;
nci.fragments = fragments;
nci.loaders = loaders;
if (mVoiceInteractor != null) {
mVoiceInteractor.retainInstance();
nci.voiceInteractor = mVoiceInteractor;
}
return nci;
}
}
/***
* ComponentActivity
*
***/
public class ComponentActivity extends androidx.core.app.ComponentActivity{
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
@Override
@Nullable
@SuppressWarnings("deprecation")
public final Object onRetainNonConfigurationInstance() {
// Maintain backward compatibility.
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;
if (viewModelStore == null) {
// No one called getViewModelStore(), so see if there was an existing
// ViewModelStore from our last NonConfigurationInstance
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
viewModelStore = nc.viewModelStore;
}
}
if (viewModelStore == null && custom == null) {
return null;
}
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.custom = custom;
nci.viewModelStore = viewModelStore;
return nci;
}
}
SaveStateHandle
上一节中分析在Activity配置发生改变时,ViewModel保存、恢复的原理,在ViewModel创建过程中还可以通过构造函数设置SaveStateHandle来获取Activity、Fragment中Intent携带bundle数据,另外在系统内存不足,APP被回收后重新进入可以通过Bundle获取之前保存的数据
SavedStateRegistryOwner
ComponentActivity、Fragment实现该接口,获取SavedStateRegistry
interface SavedStateRegistryOwner : LifecycleOwner {
/**
* The [SavedStateRegistry] owned by this SavedStateRegistryOwner
*/
val savedStateRegistry: SavedStateRegistry
}
class ComponentActivity extends SavedStateRegistryOwner...{
final SavedStateRegistryController mSavedStateRegistryController =
SavedStateRegistryController.create(this);
......
@NonNull
@Override
public final SavedStateRegistry getSavedStateRegistry() {
return mSavedStateRegistryController.getSavedStateRegistry();
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mSavedStateRegistryController.performRestore(savedInstanceState);
}
@CallSuper
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
mSavedStateRegistryController.performSave(outState);
}
}
SavedStateRegistryController
是ComponentActivity、Fragment的成员变量,持有一个savedStateRegistry,对saveStateRegistry的方法进行封装(外观模式),减少对外暴露方法数量,在保存、恢复Bundle数据时增加生命周期判断逻辑
class SavedStateRegistryController private constructor(private val owner: SavedStateRegistryOwner) {
val savedStateRegistry: SavedStateRegistry = SavedStateRegistry()
private var attached = false
@MainThread
fun performAttach() {
val lifecycle = owner.lifecycle
check(lifecycle.currentState == Lifecycle.State.INITIALIZED) {
("Restarter must be created only during owner's initialization stage")
}
lifecycle.addObserver(Recreator(owner))
savedStateRegistry.performAttach(lifecycle)
attached = true
}
@MainThread
fun performRestore(savedState: Bundle?) {
if (!attached) {
performAttach()
}
val lifecycle = owner.lifecycle
check(!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
("performRestore cannot be called when owner is ${lifecycle.currentState}")
}
savedStateRegistry.performRestore(savedState)
}
@MainThread
fun performSave(outBundle: Bundle) {
savedStateRegistry.performSave(outBundle)
}
companion object {
@JvmStatic
fun create(owner: SavedStateRegistryOwner): SavedStateRegistryController {
return SavedStateRegistryController(owner)
}
}
}
SavedStateRegistry
成员变量components用来存放实现SavedStateProvider接口的对象,需要保存Bundle的数据都必须实现该接口,
class SavedStateRegistry internal constructor() {
private val components = SafeIterableMap<String, SavedStateProvider>()
private var attached = false
private var restoredState: Bundle? = null
/**
* 上文分析在Activity\Fragment onCreate中调用
**/
internal fun performRestore(savedState: Bundle?) {
check(attached) {
("You must call performAttach() before calling " +
"performRestore(Bundle).")
}
check(!isRestored) { "SavedStateRegistry was already restored." }
restoredState = savedState?.getBundle(SAVED_COMPONENTS_KEY)
isRestored = true
}
/**
* 遍历所有实现SavedStateProvider接口中回调的Bundle,进行汇总保存到Key为
* SAVED_COMPONENTS_KEY的vaule中
**/
@MainThread
@Suppress("INACCESSIBLE_TYPE")
fun performSave(outBundle: Bundle) {
val components = Bundle()
if (restoredState != null) {
components.putAll(restoredState)
}
val it: Iterator<Map.Entry<String, SavedStateProvider>> =
this.components.iteratorWithAdditions()
while (it.hasNext()) {
val (key, value) = it.next()
components.putBundle(key, value.saveState())
}
if (!components.isEmpty) {
outBundle.putBundle(SAVED_COMPONENTS_KEY, components)
}
}
fun interface SavedStateProvider {
fun saveState(): Bundle
}
private companion object {
private const val SAVED_COMPONENTS_KEY =
"androidx.lifecycle.BundlableSavedStateRegistry.key"
}
}
SavedStateHandleController
回顾SavedStateViewModelFactory中创建ViewModel时,传递SavedStateHandle实现方式,创建controller对象就是SavedStateHandleController
fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
......
val controller = LegacySavedStateHandleController.create(
savedStateRegistry, lifecycle, key, defaultArgs
)
......
}
class LegacySavedStateHandleController {
.......
static SavedStateHandleController create(SavedStateRegistry registry, Lifecycle lifecycle,
String key, Bundle defaultArgs) {
//key为ViewModel的key,疑问点何时注册key为ViewModel的Bundle
Bundle restoredState = registry.consumeRestoredStateForKey(key);
//根据Bundles生成SavedStateHandle
SavedStateHandle handle = SavedStateHandle.createHandle(restoredState, defaultArgs);
//创建SavedStateHandleController
SavedStateHandleController controller = new SavedStateHandleController(key, handle);
controller.attachToLifecycle(registry, lifecycle);
tryToAddRecreator(registry, lifecycle);
return controller;
}
......
}
Recreator和OnRecreation
在Activity重新创建时,就会执行到该流程
static final class OnRecreation implements SavedStateRegistry.AutoRecreated {
@Override
public void onRecreated(@NonNull SavedStateRegistryOwner owner) {
if (!(owner instanceof ViewModelStoreOwner)) {
throw new IllegalStateException(
"Internal error: OnRecreation should be registered only on components"
+ " that implement ViewModelStoreOwner");
}
ViewModelStore viewModelStore = ((ViewModelStoreOwner) owner).getViewModelStore();
SavedStateRegistry savedStateRegistry = owner.getSavedStateRegistry();
for (String key : viewModelStore.keys()) {
ViewModel viewModel = viewModelStore.get(key);
attachHandleIfNeeded(viewModel, savedStateRegistry, owner.getLifecycle());
}
if (!viewModelStore.keys().isEmpty()) {
savedStateRegistry.runOnNextRecreation(OnRecreation.class);
}
}