一.前言
- 本篇主线包含三个方面,ViewModel是什么、如何使用、源码分析(包含核心类和复用原理)三个方面;
二.ViewModel是什么
-
ViewModel类是被设计用来以可感知生命周期(只能感知宿主的销毁)的方式存储和管理 UI 相关数据,ViewModel中数据会一直存活即使 activity configuration发生变化,比如横竖屏切换的时候。
-
优点
- 数据持久化(配置更改时保存数据,临时性内存存储,仅在应用进程存活期间有效);
- 异步回调问题,不会造成内存泄漏(ViewModel 的生命周期比 Activity/Fragment 长,且不持有它们的引用);
- 在Mvvm架构中隔离Model层与View层;
- 可实现Fragments间共享数据;
-
为了便于理解,结合使用场景做一下相关的总结:
- 在比较早的时候,Activity因为横竖屏切换等原因被销毁,这种异常情况下终止的,系统会调用onSaveInstanceState来保存当前Activity的状态。当Activity被重新创建后,系统会调用onRestoreInstanceState,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法。如果被重建了,那么我们就可以取出之前保存的数据并恢复,如果使用了ViewModel,这些工作ViewModel就可以替我们去做了。
- 在MVVM架构中,VM层是通过自定义ViewModel来实现的,结合Livedata一起使用,VM层是不需要持有UI层的引用就能做到驱动V层UI的更新,能写出耦合性更高、更易于维护的代码;
三.使用
- 依赖
androidx.appcompat:appcompat:1.6.1
//新建的AS项目,默认包含依赖,androidx.appcompat:appcompat:1.6.1 ,其默认有lifecycle-viewmodel,对应版本为2.6.1。
//为了让学习更简单化,就不额外添加依赖 & 选择使用Java语言的方式来进行使用和分析
- 定义MyViewModel类
public class MyViewModel extends ViewModel {
private MutableLiveData<String> number;
public MutableLiveData<String> getNumber(){
if(number == null){
number = new MutableLiveData<>();
number.setValue("");
}
return number;
}
public String getUserFromNet(){
//获取数据
return number.getValue() + "";
}
}
- 在MainActivity中使用
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
TextView mTextView;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.text);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
}
public void changeData(View view) {
myViewModel.getNumber().setValue(myViewModel.getNumber().getValue() + 1);
mTextView.setText(myViewModel.getUserFromNet());
}
}
四.ViewModel的复用原理
4.1.核心类
- ViewModelProvider:协调创建和获取 ViewModel;
- ViewModelStoreOwner:接口,其实现类提供 ViewModelStore
- ComponentActivity类实现了该接口 & 复写了接口中的getViewModelStore()方法;
- ComponentActivity类还实现了 HasDefaultViewModelProviderFactory 接口 & 重写了getDefaultViewModelProviderFactory 函数,在4.2中分析Factory的实现类时会使用到;
- ViewModelStore:存储 ViewModel 实例的容器,本质是一个HashMap;
- Factory:接口,解耦 ViewModel 的创建逻辑,有三个实现类,NewInstanceFactory、AndroidViewModelFactory和SavedStateViewModelFactory;
- SavedStateHandle:一个ViewModel对应一个SavedStateHandle,用于存储和恢复;
4.2.如何获取ViewModel的实例
- 将new ViewModelProvider(this).get(MyViewModel.class)拆分为两部分进行分析,查看ViewModelProvider和get,先分析前者:
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))
//调用另外一个构造函数
constructor(
private val store: ViewModelStore,
private val factory: Factory,
private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
)
- 由于MainActivity间接继承自ComponentActivity,ComponentActivity实现了ViewModelStoreOwner接口,则可以直接传入this作为参数。
- 将store(activity)赋值给ComponentActivity类中mViewModelStore(owner.viewModelStore对应的是ComponentActivity类中的getViewModelStore()函数,返回值是ComponentActivity类中的mViewModelStore变量)
- 分析ViewModelStore类,本质是一个Hashmap
open class ViewModelStore {
private val map = mutableMapOf<String, ViewModel>()
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun put(key: String, viewModel: ViewModel) {
val oldViewModel = map.put(key, viewModel)
oldViewModel?.onCleared()
}
/**
* Returns the `ViewModel` mapped to the given `key` or null if none exists.
*/
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
operator fun get(key: String): ViewModel? {
return map[key]
}
/**
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun keys(): Set<String> {
return HashSet(map.keys)
}
/**
* Clears internal storage and notifies `ViewModel`s that they are no longer used.
*/
fun clear() {
for (vm in map.values) {
vm.clear()
}
map.clear()
}
}
- 接着分析get函数
- 分析1:获取类的完全限定名,格式为:包名.类名(例如 com.example.MyViewModel);
- 分析2:将DEFAULT_KEY拼接canonicalName作为get函数的参数1;
- 分析3:根据key获取ViewModel;
- 分析4:检查缓存实例是否是 modelClass 类型,符合则返回store[key];
- 分析5:如果没有找到合适的实例,准备创建新的ViewModel;
- 分析6:优先使用factory带extras参数的create方法;
- 分析7:回退到factory不带extras参数的create方法;
- 分析8:将新创建的ViewModel存入store;
@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
//分析1
val canonicalName = modelClass.canonicalName
?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
//分析2
return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
val viewModel = store[key]//分析3
if (modelClass.isInstance(viewModel)) {//分析4
(factory as? OnRequeryFactory)?.onRequery(viewModel!!)
return viewModel as T
} else {
@Suppress("ControlFlowWithEmptyBody")
if (viewModel != null) {
// TODO: log a warning.
}
}
val extras = MutableCreationExtras(defaultCreationExtras)//分析5
extras[VIEW_MODEL_KEY] = key
// AGP has some desugaring issues associated with compileOnly dependencies so we need to
// fall back to the other create method to keep from crashing.
return try {
factory.create(modelClass, extras)//分析6
} catch (e: AbstractMethodError) {
factory.create(modelClass)//分析7
}.also { store.put(key, it) }//分析8
}
- 因为factory是接口,我们需要找到具体实现类,回到ViewModelProvider构造函数中发现,factory的赋值时机是调用了defaultFactory函数
- 分析9:条件成立
- owner.defaultViewModelProviderFactory对应为ComponentActivity中的getDefaultViewModelProviderFactory函数
public companion object {
internal fun defaultFactory(owner: ViewModelStoreOwner): Factory =
if (owner is HasDefaultViewModelProviderFactory)//分析9
owner.defaultViewModelProviderFactory else instance
//...
}
- ComponentActivity中的getDefaultViewModelProviderFactory函数,即:
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
- 此时,我们看一下Factory的源码,Factory带extras参数的create函数最终还是重载不带extras参数的create(modelClass) 方法
public interface Factory {
public fun <T : ViewModel> create(modelClass: Class<T>): T {
throw UnsupportedOperationException(
"Factory.create(String) is unsupported. This Factory requires " +
"`CreationExtras` to be passed into `create` method."
)
}
//...
public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =
create(modelClass)
//...
}
- 回到上方的get函数,不论是执行分析6还是分析7,根据前面的推理,我们可以知晓,代码最终要执行的是SavedStateViewModelFactory类的create(modelClass: Class
) 函数,继续查看会执行create(key: String, modelClass: Class )函数,源码如下:
fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
// empty constructor was called.
//检查lifecycle是否存在
val lifecycle = lifecycle
?: throw UnsupportedOperationException(
"SavedStateViewModelFactory constructed with empty constructor supports only " +
"calls to create(modelClass: Class<T>, extras: CreationExtras)."
)
//分析10
val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass)
//分析11
val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) {
//分析12
findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE)
} else {
//分析13
findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE)
}
//分析14
// doesn't need SavedStateHandle
constructor
?: // If you are using a stateful constructor and no application is available, we
// use an instance factory instead.
return if (application != null) factory.create(modelClass)//分析15
else instance.create(modelClass)//分析16
//分析17
val controller = LegacySavedStateHandleController.create(
savedStateRegistry!!, lifecycle, key, defaultArgs
)
//分析18
val viewModel: T = if (isAndroidViewModel && application != null) {
newInstance(modelClass, constructor, application!!, controller.handle)
} else {
newInstance(modelClass, constructor, controller.handle)
}
//分析19
viewModel.setTagIfAbsent(
AbstractSavedStateViewModelFactory.TAG_SAVED_STATE_HANDLE_CONTROLLER, controller
)
//分析20
return viewModel
}
- 分析10:判断要创建的ViewModel是否是AndroidViewModel的子类
- 分析11:根据ViewModel类型查找匹配的构造函数,查看一下findMatchingConstructor函数(上方代码中,由于 MyViewModel 只有无参构造器,findMatchingConstructor 会返回 null)
private val ANDROID_VIEWMODEL_SIGNATURE = listOf<Class<*>>(
Application::class.java,
SavedStateHandle::class.java
)
private val VIEWMODEL_SIGNATURE = listOf<Class<*>>(SavedStateHandle::class.java)
//内部函数,泛型T表示目标类型,查找modelClass中与signature参数列表匹配的构造函数
internal fun <T> findMatchingConstructor(
modelClass: Class<T>,// 要查找的类对象
signature: List<Class<*>>// 期望的参数类型列表
): Constructor<T>? {// 返回找到的构造器或null
// 11.1. 遍历目标类的所有构造函数
for (constructor in modelClass.constructors) {
// 11.2. 获取当前构造函数的参数类型列表
val parameterTypes = constructor.parameterTypes.toList()
// 11.3. 检查参数类型是否完全匹配signature
if (signature == parameterTypes) {
// 11.4. 类型匹配时,抑制类型转换警告并返回构造器
@Suppress("UNCHECKED_CAST")
return constructor as Constructor<T>
}
// 11.5. 检查参数数量相同但顺序不对的情况
if (signature.size == parameterTypes.size && parameterTypes.containsAll(signature)) {
// 11.6. 抛出异常提示参数顺序错误
throw UnsupportedOperationException(
"Class ${modelClass.simpleName} must have parameters in the proper " +
"order: $signature"
)
}
}
// 11.7. 没有找到匹配的构造函数则返回null
return null
}
-
分析12:如果是AndroidViewModel且有Application上下文,查找带Application和SavedStateHandle参数的构造器
-
分析13:普通ViewModel,查找带SavedStateHandle参数的构造器
-
分析14,因为分析11位置得到的结果constructor是为null,所以这里要么执行分析15,要么执行分析16。两者执行其中一个之后,方法就return,后面代码就不执行了。附上一张流程图
- 分析15:factory = ViewModelProvider.AndroidViewModelFactory(),即:执行AndroidViewModelFactory的create函数;
- 分析16:sInstance = NewInstanceFactory(),即:执行NewInstanceFactory的create函数;
-
分析17:创建SavedStateHandleController
-
分析18:根据构造器参数创建viewModel(将 SavedStateHandle 注入到 ViewModel 中)
-
分析19:为viewModel加上标签
-
分析20:返回viewModel
-
总结:ViewModelProvider,本质是从传递进去的ViewModelStoreOwner来获取实例,如果没有,则利用Factory来创建。而Factory有三个实现类,其区别如下:
- NewInstanceFactory:直接反射构建出viewModel;
- AndroidViewModelFactory:构建时需要传递一个Application;
- SavedStateViewModelFactory:构建时会传递一个SavedStateHandle对象,可以取代onSaveInstanceState 和 onRestoreInstanceState用来存储和恢复数据。这种存储方式,即使页面因配置变更、内存不足被系统回收,重建时都可以恢复数据;
-
Factory的create(modelClass) 方法执行具体是指向哪个实现类由我们所写的代码方式来决定,我们分别举例一个场景来说明:
- 未指定 Factory & ViewModel 必须有无参构造函数,则使用的 Factory的create(modelClass) 方法对应为NewInstanceFactory;
//V层中调用 myViewModel = new ViewModelProvider(this).get(MyViewModel.class); //MyViewModel类,ViewModel 必须有无参构造函数 public class MyViewModel extends ViewModel { private MutableLiveData<String> number; public MutableLiveData<String> getNumber(){ if(number == null){ number = new MutableLiveData<>(); number.setValue(""); } return number; } public String getUserFromNet(){ //获取数据 return number.getValue() + ""; } }
- ViewModel继承 AndroidViewModel & 显式指定 AndroidViewModelFactory,则使用的 Factory的create(modelClass) 方法对应为AndroidViewModelFactory;
// V层显式使用 AndroidViewModelFactory val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application) val viewModel = ViewModelProvider(this, factory).get(MyAndroidViewModel::class.java) //ViewModel自定义类中需要继承 AndroidViewModel class MyAndroidViewModel(application: Application) : AndroidViewModel(application)
- ViewModel 需要接收 SavedStateHandle 参数,则使用的 Factory的create(modelClass) 方法对应为SavedStateViewModelFactory;
// V层使用,默认使用 SavedStateViewModelFactory(自动注入 SavedStateHandle) val viewModel = ViewModelProvider(this).get(MyStateViewModel::class.java) // ViewModel实现类自定义构造 class MyStateViewModel(savedStateHandle: SavedStateHandle) : ViewModel() { //... //savedStateHandle["指定的key"]//获取对应key的数据 //savedStateHandle["指定的key"] = “目标的数据”//保存指定key的数据 }
4.3.ViewModel实例的复用原理
- 我们直接分析使用SavedStateHandle的情况下复用原理,若这种情况弄明白的话,不使用SavedStateHandle的情况下的复用则自然就清楚了。
- 前置知识,在分析源码之前,需要知道2点:配置变更(如旋转屏幕)或因为内存不足导致进程被杀后重建触发ActivityThread的handleRelaunchActivity,且随后会调用performLaunchActivity函数(大体流程:handleRelaunchActivity->handleRelaunchActivityInner->handleLaunchActivity->performLaunchActivity)& 带SavedStateHandle的ViewModel的简单使用;
- 源码分析的大体结构如下:MainActivity的onCreate->Factory(对应SavedStateViewModelFactory实现类)的create函数(不带extras参数)->…->配置变更(如旋转屏幕)或因为内存不足导致进程被杀后重建触发->ActivityThread的handleRelaunchActivity->performPauseActivity(内部调用了对应Activity的OnSaveInstanceState函数) & handleDestroyActivity(处理NonConfigurationInstances类相关的)->performLaunchActivity->Activity类中 attach函数 & 对应Activity的onCreate函数->val viewModel = ViewModelProvider(this).get(MyStateViewModel::class.java);
4.3.1.首次执行onCreate函数
- 根据4.3之前的内容可以知道,我们直接分析SavedStateViewModelFactory类的create(key: String, modelClass: Class
)函数中的LegacySavedStateHandleController.create函数,因为使用的是带SavedStateHandle,一定会执行到这里。
fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
//...
val controller = LegacySavedStateHandleController.create(
savedStateRegistry!!, lifecycle, key, defaultArgs
)
//...
}
- LegacySavedStateHandleController的create函数,我们重点关注controller.attachToLifecycle(registry, lifecycle),其它的代码一会儿回头进行分析更合适
fun create(
registry: SavedStateRegistry,
lifecycle: Lifecycle,
key: String?,
defaultArgs: Bundle?
): SavedStateHandleController {
val restoredState = registry.consumeRestoredStateForKey(key!!)
val handle = createHandle(restoredState, defaultArgs)
val controller = SavedStateHandleController(key, handle)
controller.attachToLifecycle(registry, lifecycle)
tryToAddRecreator(registry, lifecycle)
return controller
}
- controller.attachToLifecycle(registry, lifecycle)函数,我们重点关注registry.registerSavedStateProvider(key, handle.savedStateProvider())
internal class SavedStateHandleController(
private val key: String,
val handle: SavedStateHandle
) : LifecycleEventObserver {
var isAttached = false
private set
fun attachToLifecycle(registry: SavedStateRegistry, lifecycle: Lifecycle) {
check(!isAttached) { "Already attached to lifecycleOwner" }
isAttached = true
lifecycle.addObserver(this)
registry.registerSavedStateProvider(key, handle.savedStateProvider())//分析21
}
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
if (event === Lifecycle.Event.ON_DESTROY) {
isAttached = false
source.lifecycle.removeObserver(this)
}
}
}
- 分析21:SavedStateRegistry类中的registerSavedStateProvider函数
fun registerSavedStateProvider(
key: String,
provider: SavedStateProvider
) {
val previous = components.putIfAbsent(key, provider)//分析22
require(previous == null) {
("SavedStateProvider with the given key is" +
" already registered")
}
}
- 分析22:components为SavedStateRegistry类中的成员变量,此时该变量有值了,在分析OnSaveInstanceState函数时会关联到变量;
private val components = SafeIterableMap<String, SavedStateProvider>()
4.3.2. ComponentActivity类的onSaveInstanceState函数
- 从ActivityThread的handleRelaunchActivity开始->handleRelaunchActivityInner->performPauseActivity->callActivityOnSaveInstanceState->对应MainActivity的onSaveInstanceState函数,我们分析其间接实现的ComponentActivity类的onSaveInstanceState函数。ActivityThread相关的源码就不展示了,我们仅展示我们要重点分析的源码。
protected void onSaveInstanceState(@NonNull Bundle outState) {
//...
mSavedStateRegistryController.performSave(outState);//分析23
}
- 分析23:mSavedStateRegistryController.performSave(outState)—>savedStateRegistry.performSave(outBundle)
fun performSave(outBundle: Bundle) {
val components = Bundle()
if (restoredState != null) {
components.putAll(restoredState)
}
val it: Iterator<Map.Entry<String, SavedStateProvider>> =
this.components.iteratorWithAdditions()//分析24
while (it.hasNext()) {
val (key, value) = it.next()
components.putBundle(key, value.saveState())
}
if (!components.isEmpty) {
outBundle.putBundle(SAVED_COMPONENTS_KEY, components)
}
}
- 分析24中有一个this.components,其就是我们在分析22位置的components,其是有值的。那么savedStateRegistry.performSave函数执行之后,outBundle.putBundle(SAVED_COMPONENTS_KEY, components)会调用成功。这里的保存操作是让Bundle来干活的。
4.3.3.配置变更对包装类NonConfigurationInstances的处理
- 从ActivityThread的handleRelaunchActivity开始->handleRelaunchActivityInner->handleDestroyActivity->performDestroyActivity->重点代码:“r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances()”,同理,ActivityThread相关的源码就不展示了,我们仅展示我们要重点分析的源码。
void performDestroyActivity(ActivityClientRecord r, boolean finishing,
boolean getNonConfigInstance, String reason) {
//...
r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances();//分析25
//...
}
- 分析25:需要拆分成两部分,r.activity.retainNonConfigurationInstances()和对r.lastNonConfigurationInstances的赋值
//Activity的retainNonConfigurationInstances()函数
NonConfigurationInstances retainNonConfigurationInstances() {
Object activity = onRetainNonConfigurationInstance();//分析26,对应实现为ComponentActivity类的 onRetainNonConfigurationInstance()
//...
NonConfigurationInstances nci = new NonConfigurationInstances();
nci.activity = activity;
//...
return nci;
}
- 分析26:ComponentActivity类的 onRetainNonConfigurationInstance(),该函数可能会返回null或者返回一个包装类NonConfigurationInstances,该包装类跟ComponentActivity类中的成员变量关联mViewModelStore。而该成员变量对应一个函数getViewModelStore()来进行获取。
public final Object onRetainNonConfigurationInstance() {
// Maintain backward compatibility.
Object custom = onRetainCustomNonConfigurationInstance();
ViewModelStore viewModelStore = mViewModelStore;// 获取当前Activity的ViewModelStore
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;//把ViewModelStore放进去
return nci;
}
- 结合分析25和26可以知晓,ComponentActivity类的 onRetainNonConfigurationInstance()返回的结果赋值给了ActivityClientRecord的lastNonConfigurationInstances;
4.3.4.分析ActivityThread中的performLaunchActivity(重建工作)
- 这里分两个小点,一个是activity.attach函数的分析,另一个是mInstrumentation.callActivityOnCreate(最终是会调用ComponentActivity类的OnCreate函数)函数的分析
- activity.attach函数:ActivityClientRecord的lastNonConfigurationInstances是该函数的参数,赋值给了Activity类中的mLastNonConfigurationInstances(类型为:NonConfigurationInstances);
final void attach(//... mLastNonConfigurationInstances = lastNonConfigurationInstances; //... }
- ComponentActivity类onCreate函数
protected void onCreate(@Nullable Bundle savedInstanceState) { //... mSavedStateRegistryController.performRestore(savedInstanceState);//分析27 //... }
- 分析27:mSavedStateRegistryController.performRestore(savedInstanceState)—>savedStateRegistry.performRestore(savedState)
internal fun performRestore(savedState: Bundle?) { //... //restoredState是SavedStateRegistry类的成员变量 restoredState = savedState?.getBundle(SAVED_COMPONENTS_KEY)//分析28 //... }
- 分析28:这里的key为SAVED_COMPONENTS_KEY,跟outBundle.putBundle(SAVED_COMPONENTS_KEY, components)的key相同 & 保存过值的,故restoredState也是有值的。
- 当ComponentActivity类onCreate函数执行完,会继续执行其实现类MainActivity的onCreate
public class MainActivity extends AppCompatActivity { //... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... myViewModel = new ViewModelProvider(this).get(MyViewModel.class); } //... }
- ViewModel数据的保存和获取已经分析完成。我们再次分析create(key: String, modelClass: Class
)函数,重点是分析SavedStateHandle的复用
4.3.4.再次分析SavedStateViewModelFactory的create(key: String, modelClass: Class)函数
fun <T : ViewModel> create(key: String, modelClass: Class<T>): T {
//...
//分析29
val controller = LegacySavedStateHandleController.create(
savedStateRegistry!!, lifecycle, key, defaultArgs
)
//分析30
val viewModel: T = if (isAndroidViewModel && application != null) {
newInstance(modelClass, constructor, application!!, controller.handle)
} else {
newInstance(modelClass, constructor, controller.handle)
}
viewModel.setTagIfAbsent(
AbstractSavedStateViewModelFactory.TAG_SAVED_STATE_HANDLE_CONTROLLER, controller
)
return viewModel
}
- 分析29,内部做了三件事
fun create(
registry: SavedStateRegistry,
lifecycle: Lifecycle,
key: String?,
defaultArgs: Bundle?
): SavedStateHandleController {
//事件1:SavedStateRegistry中获取 之前保存起来的Bundle数据
val restoredState = registry.consumeRestoredStateForKey(key!!)
//事件2:(使用事件1中获取的数据来)创建SavedStateHandle对象
val handle = createHandle(restoredState, defaultArgs)
val controller = SavedStateHandleController(key, handle)
//事件3:调用SavedStateRegistry的registerSavedStateProvider函数 向数据的存储中心注册一个savedStateProvider
controller.attachToLifecycle(registry, lifecycle)
tryToAddRecreator(registry, lifecycle)
return controller
}
- 事件1位置的相关源码,在分析28中我们知晓,下方restoredState是有值的,故事件1位置得到的restoredState也是有值的。
@MainThread
fun consumeRestoredStateForKey(key: String): Bundle? {
//...
if (restoredState != null) {
val result = restoredState?.getBundle(key)
restoredState?.remove(key)
if (restoredState?.isEmpty != false) {
restoredState = null
}
return result
}
return null
}
- 事件2位置源码分析
fun createHandle(restoredState: Bundle?, defaultState: Bundle?): SavedStateHandle {
if (restoredState == null) {
return if (defaultState == null) {
// No restored state and no default state -> empty SavedStateHandle
SavedStateHandle()
} else {
val state: MutableMap<String, Any?> = HashMap()
for (key in defaultState.keySet()) {
state[key] = defaultState[key]
}
SavedStateHandle(state)
}
}
//...
val keys: ArrayList<*>? = restoredState.getParcelableArrayList<Parcelable>(KEYS)
val values: ArrayList<*>? = restoredState.getParcelableArrayList<Parcelable>(VALUES)
//...
val state = mutableMapOf<String, Any?>()
for (i in keys.indices) {
state[keys[i] as String] = values[i]
}
return SavedStateHandle(state)//分析31
}
- 分析31:创建SavedStateHandle时,将传递进来的Bundle类型的restoredState中的数据赋值给Map,然后将该Map通过SavedStateHandle的构造进行传入。即:创建的SavedStateHandle拥有了之前存储到Bundle中的数据了。
- 分析30:无论是newInstance(modelClass, constructor, application!!, controller.handle)还是执行newInstance(modelClass, constructor, controller.handle),将恢复的Handle(controller.handle)注入到对应的ViewModel实现类的构造函数中,其saveState就有值了,SavedStateHandle的复用也就走通了。数据通过系统机制保存到Bundle,重建时又从Bundle中取出并用于初始化一个新的SavedStateHandle,最后注入到新的ViewModel中。ViewModel实例是新的,但数据是旧的。
4.3.5.ViewModelStore的复用
- 主要依赖于ComponentActivity类中onRetainNonConfigurationInstance() 和 getViewModelStore() 这两个方法的配合
- onRetainNonConfigurationInstance对应ViewModelStore的保存,在因配置变更而销毁Activity之前,系统会调用此方法。最终是会保存到ActivityClientRecord的lastNonConfigurationInstances中,前面已经分析过;
- 查看ComponentActivity类的getViewModelStore函数,对应为ViewModelStore的获取;
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached to the "
+ "Application instance. You can't request ViewModel before onCreate call.");
}
ensureViewModelStore();
return mViewModelStore;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
void ensureViewModelStore() {
if (mViewModelStore == null) {
NonConfigurationInstances nc =
(NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
// Restore the ViewModelStore from NonConfigurationInstances
mViewModelStore = nc.viewModelStore;//复用了旧的ViewModelStore
}
if (mViewModelStore == null) {
mViewModelStore = new ViewModelStore();
}
}
}
- 当mViewModelStore为空的时候,会尝试从 getLastNonConfigurationInstance函数中进行获取,而Activity类中的mLastNonConfigurationInstances赋值时机在4.3.4中提及的attach函数中进行赋值的,为ActivityClientRecord的lastNonConfigurationInstances。而ActivityClientRecord的lastNonConfigurationInstances正好是onRetainNonConfigurationInstance返回的结果,即:取出的ViewModelStore为保存的ViewModelStore,两者是同一个。
public Object getLastNonConfigurationInstance() {
return mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.activity : null;
}
- 不论是否使用SavedStateHandle都会缓存到 ViewModelStore(本质是一个HashMap)中,当因为内存不足等原因发生的重建ViewModel和ViewModelStore都会被销毁的;
五.总结
- 本文重点对ViewModel的复用原理的详细细节展开了分析,分两种情况,带SavedStateHandle的情况下与不带SavedStateHandle的情况。其中,前者即使应用因内存不足导致进程被杀掉后重建,虽然重建前后的ViewModel不是同一个,但ViewModel依旧可以复用,其底层依赖于Bundle,而因配置文件改变的重建,复用的是同一个ViewModel;而后者在应用进程被杀掉的情况下是不能实现复用的,因配置改变重建是可以实现复用的,重建前后复用的是同一个ViewModel;
评论区