Android ViewModel源码梳理
ViewModel生命周期探究
前言
对ViewModel的使用一直处于会用但不清楚原理的阶段,目前有闲暇时间,探究一下ViewModel原理
前置条件
- Android Compile SDK: 33
- Dependency:
- androidx.core:core-ktx:1.9.0
- androidx.appcompat:appcompat:1.6.1
- androidx.activity:activity-ktx:1.7.0
长篇源码警告
核心
ViewModelStoreOwner
持有ViewModelStore的对象,具有自己的生命周期. (Activity / Fragment 或其他自定义生命周期的View)
interface ViewModelStoreOwner {
/**
* The owned [ViewModelStore]
*/
val viewModelStore: ViewModelStore
}
ViewModelStore
ViewModelStore持有ViewModel的最终管理集合(实质为LinkedHashMap),并以<String, ViewModel>
的方式存储
open class ViewModelStore {
private val map = mutableMapOf<String, ViewModel>()
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun put(key: String, viewModel: ViewModel) {
val oldViewModel = map.put(key, viewModel)
oldViewModel?.onCleared()
}
// ...
}
ViewModelProvider
Jetpack中提供ViewModel的工具类(主要是创建ViewModel),通过Factory + Extras来进行基于不同功能的ViewModle的创建
生命周期
如何创建
重点理解ViewModel构造ViewModel时采用的链式构造模式,通过工厂模式,并内部使用继承/聚合的关系,从高级到低级工厂尝试构造符合当前ViewModel到实例对象。不满足上级条件则交由下一级构造,若不成功则继续交由下一级构造...
通过ViewModelProvider
在Activity中我们经常使用ViewModelProvier(this)[MViewModel::class.java]
获取唯一的ViewModel实例,ViewModel是通过ViewModelProvider进行创建的,那么就从ViewModelProvider的构建开始, 假设要构造一个无参的ViewModel
public open class ViewModelProvider constructor(
private val store: ViewModelStore,
private val factory: Factory,
private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
) {
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))
}
即通过ViewModelProvier(this)[MViewModel::class.java]
这种方式创建ViewModel时,ViewModelProvider初始化时使用了默认的Factory与Extras
看一下构造时传入的ViewModelStoreOwner与ViewModelStore。ViewModelStore相当于保存了多个ViewModel的一个存储结构,以KV键值对保存ViewModel,存储结构为LinkedHashMap
interface ViewModelStoreOwner {
val viewModelStore: ViewModelStore
}
open class ViewModelStore {
private val map = mutableMapOf<String, ViewModel>()
@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.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
operator fun get(key: String): ViewModel? {
return map[key]
}
@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()
}
那么Activity调用时传入this,那肯定Activity是实现了ViewModelStoreOwner接口的,最终在ComponentActivity中找到在getViewModelStore时复用或创建该ViewModelStore
// ComponentActivity
//
private ViewModelStore mViewModelStore;
private ViewModelProvider.Factory mDefaultFactory;
@Override
public ViewModelStore getViewModelStore() {
if (getApplication() == null) {
throw new IllegalStateException();
}
ensureViewModelStore();
return mViewModelStore;
}
// 确保mViewModelStore进行了初始化
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();
}
}
}
现在我们知道了如何创建ViewModelProvier了,那ViewModelProvier中get方法做了什么呢?
- 通过默认的key前缀与Class的canonicalName组合成Key
- 通过该key查找ViewModelStore中Map保存的ViewModel
- 如果已经有实例了,那直接返回
- 如果没有该实例,通过factory以及extra配置创建该ViewModel,调用的是factory中的create方法
// 注意, 该方法只能在主线程中调用
@MainThread
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
// canoncialName为返回一个类 易理解的 名称
val canonicalName = modelClass.canonicalName
?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
val viewModel = store[key]
// 判断VMStore中存的vm是否是目标class的类型
if (modelClass.isInstance(viewModel)) {
// 调用Factory的回调
(factory as? OnRequeryFactory)?.onRequery(viewModel)
return viewModel as T
} else {
@Suppress("ControlFlowWithEmptyBody")
if (viewModel != null) {
// TODO: log a warning.
}
}
val extras = MutableCreationExtras(defaultCreationExtras)
extras[VIEW_MODEL_KEY] = key
// 如果没有该实例,则通过fatcory创建
return try {
factory.create(modelClass, extras)
} catch (e: AbstractMethodError) {
factory.create(modelClass)
}.also { store.put(key, it) }
}
这里factory是如何创造的呢?通过最开始初始化构建,我们知道是调用了内部构造默认factory的方法,这里逻辑稍微有点绕,但其实最后创建了SavedStateViewModelFactory
看一下构造ViewModelProvider时创建Factory的默认方法
public open class AndroidViewModelFactory
private constructor(
private val application: Application?,
// parameter to avoid clash between constructors with nullable and non-nullable
// Application
@Suppress("UNUSED_PARAMETER") unused: Int,
) : NewInstanceFactory() {
public companion object {
internal fun defaultFactory(owner: ViewModelStoreOwner): Factory =
if (owner is HasDefaultViewModelProviderFactory)
owner.defaultViewModelProviderFactory else instance
@JvmStatic
public fun getInstance(application: Application): AndroidViewModelFactory {
if (sInstance == null) {
sInstance = AndroidViewModelFactory(application)
}
return sInstance!!
}
}
}
而ComponentActivity实现了接口HasDefaultViewModelProviderFactory
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
if (mDefaultFactory == null) {
mDefaultFactory = new SavedStateViewModelFactory(
getApplication(),
this,
getIntent() != null ? getIntent().getExtras() : null);
}
return mDefaultFactory;
}
class SavedStateViewModelFactory : ViewModelProvider.OnRequeryFactory, ViewModelProvider.Factory {
private var application: Application? = null
private val factory: ViewModelProvider.Factory
private var defaultArgs: Bundle? = null
private var lifecycle: Lifecycle? = null
private var savedStateRegistry: SavedStateRegistry? = null
constructor(application: Application?, owner: SavedStateRegistryOwner, defaultArgs: Bundle?) {
savedStateRegistry = owner.savedStateRegistry
lifecycle = owner.lifecycle
this.defaultArgs = defaultArgs
this.application = application
factory = if (application != null) getInstance(application)
else ViewModelProvider.AndroidViewModelFactory()
}
public fun getInstance(application: Application): AndroidViewModelFactory {
if (sInstance == null) {
sInstance = AndroidViewModelFactory(application)
}
return sInstance!!
}
}
这里SavedStateViewModelFactory可以理解为持有Application对象的ViewModelFactory, 类似装饰者模式, SavedStateViewModelFactory维护了一个Factory, 实质为AndroidViewModelFactory
, 而AndroidViewModelFactory为NewInstanceFactory的派生类,请记住以上的层级关系
以下开始探究factory.create调用的层级关系
// SavedStateViewModelFactory
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
val key = extras[ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY]
?: throw IllegalStateException(
"VIEW_MODEL_KEY must always be provided by ViewModelProvider"
)
return if (extras[SAVED_STATE_REGISTRY_OWNER_KEY] != null &&
extras[VIEW_MODEL_STORE_OWNER_KEY] != null) {
val application = extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY]
val isAndroidViewModel = AndroidViewModel::class.java.isAssignableFrom(modelClass)
// 判断是否是AndroidViewModel
// 并尝试根据是否需要SavedStateHandle来构造constructor(一般不需要)
val constructor: Constructor<T>? = if (isAndroidViewModel && application != null) {
findMatchingConstructor(modelClass, ANDROID_VIEWMODEL_SIGNATURE)
} else {
findMatchingConstructor(modelClass, VIEWMODEL_SIGNATURE)
}
// 如果不需要SavedStateHandle, 则通过内置factory构造ViewModel(一般为AndroidViewModelFactory)
if (constructor == null) {
return factory.create(modelClass, extras)
}
val viewModel = if (isAndroidViewModel && application != null) {
newInstance(modelClass, constructor, application, extras.createSavedStateHandle())
} else {
newInstance(modelClass, constructor, extras.createSavedStateHandle())
}
viewModel
} else {
val viewModel = if (lifecycle != null) {
create(key, modelClass)
} else {
throw IllegalStateException("SAVED_STATE_REGISTRY_OWNER_KEY and" +
"VIEW_MODEL_STORE_OWNER_KEY must be provided in the creation extras to" +
"successfully create a ViewModel.")
}
viewModel
}
}
// AndroidViewModelFactory
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {
return if (application != null) {
create(modelClass)
} else {
val application = extras[APPLICATION_KEY]
if (application != null) {
create(modelClass, application)
} else {
// For AndroidViewModels, CreationExtras must have an application set
if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
throw IllegalArgumentException(
"CreationExtras must have an application by `APPLICATION_KEY`"
)
}
super.create(modelClass)
}
}
}
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return if (application == null) {
throw UnsupportedOperationException(
"AndroidViewModelFactory constructed " +
"with empty constructor works only with " +
"create(modelClass: Class<T>, extras: CreationExtras)."
)
} else {
create(modelClass, application)
}
}
@Suppress("DocumentExceptions")
private fun <T : ViewModel> create(modelClass: Class<T>, app: Application): T {
// 判断是否是AndroidViewModel, 若是则根据Application创建ViewModel
return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {
try {
modelClass.getConstructor(Application::class.java).newInstance(app)
} catch (e: NoSuchMethodException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: InstantiationException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: InvocationTargetException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
}
// 一般ViewModel最终走这个逻辑
} else super.create(modelClass)
}
// NewInstanceFactory
@Suppress("DocumentExceptions")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return try {
// 使用ViewModel::class的无参构器构造该对象
modelClass.getDeclaredConstructor().newInstance()
} catch (e: NoSuchMethodException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: InstantiationException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
} catch (e: IllegalAccessException) {
throw RuntimeException("Cannot create an instance of $modelClass", e)
}
}
由上述分析,因为存在SavedStateViewModelFactory -> AndroidViewModelFactory -> NewInstanceFactory->newInstance这样的链关系,因此此时调用create方法时也存在一系列调用链的关系,其create方法根据extras信息做了一些判断,最后又调用到ViewModelProvier中AndroidViewModelFactory方法的create方法,做了一些判断,当不满足后又调用到NewInstanceFactory的create方法,最终通过反射构造了一个无参的ViewModel
至此,一个普通的无参ViewModel便构造完成了。
by viewModels()
经常使用的方式为委托方式,具体为
private val mViewModel: BaseViewModel by viewModels()
需要添加以下依赖"androidx.activity:activity-ktx:1.2.0"
Tips: 这里思考一下为什么使用reified关键字?
优点: 可以直接使用::class对象而不需要再传入表示class的klazz参数
// ActivityViewModelLazy.kt
@MainThread
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
noinline extrasProducer: (() -> CreationExtras)? = null,
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
// 实际为ComponentActivity中的mDefaultFactory(SavedStateViewModelFactory)
defaultViewModelProviderFactory
}
return ViewModelLazy(
VM::class,
{ viewModelStore },
factoryPromise,
{ extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras }
)
}
// FragmentViewModelLazy.kt
@MainThread
inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
noinline factoryProducer: (() -> Factory)? = null
) = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
该委托方式为ComponentActivity及派生类才能调用, 实际返回的是基于Lazy接口的ViewModelLazy类
public class ViewModelLazy<VM : ViewModel> @JvmOverloads constructor(
private val viewModelClass: KClass<VM>,
private val storeProducer: () -> ViewModelStore,
private val factoryProducer: () -> ViewModelProvider.Factory,
private val extrasProducer: () -> CreationExtras = { CreationExtras.Empty }
) : Lazy<VM> {
private var cached: VM? = null
// 延迟加载实际逻辑, get时才会初始化
override val value: VM
get() {
val viewModel = cached
// 有cached就用cache
return if (viewModel == null) {
val factory = factoryProducer()
val store = storeProducer()
// 实际还是使用ViewModelProvider构造ViewModel
ViewModelProvider(
store,
factory,
extrasProducer()
).get(viewModelClass.java).also {
cached = it
}
} else {
viewModel
}
}
override fun isInitialized(): Boolean = cached != null
}
by activityViewModels()
可以看出,fragment中使用activityViewModels创建的ViewModel是依附于对应的Activity到viewModelStore,所以其生命周期与对应的Activity绑定
// FragmentViewModelLazy.kt
@MainThread
inline fun <reified VM : ViewModel> Fragment.activityViewModels(
noinline factoryProducer: (() -> Factory)? = null
// 关键代码
) = createViewModelLazy(VM::class, { requireActivity().viewModelStore }, factoryProducer)
@MainThread
fun <VM : ViewModel> Fragment.createViewModelLazy(
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
val application = activity?.application ?: throw IllegalStateException(
"ViewModel can be accessed only when Fragment is attached"
)
AndroidViewModelFactory.getInstance(application)
}
return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
}
如何销毁
我们知道ViewModel在Activity 销毁时进行销毁,那具体是如何实现的呢?
在FragmentActivity时的onDestroy方法中,会通过Lifecycle机制进行通知(从之前探究Lifecycle机制的文章中有详细介绍)
@Override
protected void onDestroy() {
super.onDestroy();
mFragments.dispatchDestroy();
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
handleLifecycleEvent中会对lifecycle的状态进行改变并进行通知,最终进入到mLifecycleObserver.onStateChanged方法中
// ComponentActivity初始化时会添加lifecycle的observer进行监听
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
// Clear out the available context
mContextAwareHelper.clearAvailableContext();
// And clear the ViewModelStore
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
这里的逻辑就很简单了,当Lifecycle为ON_DESTROY时,就对VMP进行清理,注意这里是清理该ViewModelStoreOwner下ViewModelStore中的所有的ViewModel!
参考网站🔗