持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情
前言
在 JetPack 组件中,ViewModel 主要用于封装与接口相关的数据。同样,ViewModel 具有生命周期感知能力。在Activity或Fragment onDetach销毁之前一直存在于内存中;尤其是屏幕旋转等系统配置变化后,ViewModel保存的界面数据依然存在。使用方式我们不用了解了,接下来让我们了解一下ViewModel的源码实现。
前言
在 JetPack 组件中,ViewModel 主要用于封装与接口相关的数据。同样,ViewModel 具有生命周期感知能力。在Activity或Fragment onDetach销毁之前一直存在于内存中;尤其是屏幕旋转等系统配置变化后,ViewModel保存的界面数据依然存在。使用方式我们不用了解了,接下来让我了解一下ViewModel的源码实现。
ViewModel的创建
viewmodels
我们从Fragment的viewModels语法糖进入源码的查看
@MainThread
public inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> = createViewModelLazy(VM::class, { ownerProducer().viewModelStore }, factoryProducer)
这是一个内联函数,参数列表是:
- ownerProducer:返回的是
ViewModelStoreOwner
类型,默认是this
,也就是当前调用函数的所有者Activity
或Fragment
。 - factoryProducer:创建ViewModel的工厂,可以为空,也可以自己定义,实现
ViewModelProvider.Factory
这个接口即可。 可以看得到viewmodels
调用了createViewModelLazy
这个方法。
createViewModelLazy
@MainThread
public fun <VM : ViewModel> Fragment.createViewModelLazy(
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
// 调用fragment的getDefaultViewModelProviderFactory方法
defaultViewModelProviderFactory
}
return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
}
// fragment
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
...
// 默认application是requireContext().getApplicationContext()
Application application = null;
Context appContext = requireContext().getApplicationContext();
while (appContext instanceof ContextWrapper) {
if (appContext instanceof Application) {
application = (Application) appContext;
break;
}
appContext = ((ContextWrapper) appContext).getBaseContext();
}
mDefaultFactory = new SavedStateViewModelFactory(
application,
this,
getArguments());
return mDefaultFactory;
}
// fragment
public SavedStateViewModelFactory(@Nullable Application application,
@NonNull SavedStateRegistryOwner owner,
@Nullable Bundle defaultArgs) {
mSavedStateRegistry = owner.getSavedStateRegistry();
mLifecycle = owner.getLifecycle();
mDefaultArgs = defaultArgs;
mApplication = application;
// 上游application不为空
mFactory = application != null
? ViewModelProvider.AndroidViewModelFactory.getInstance(application)
: ViewModelProvider.NewInstanceFactory.getInstance();
}
如果传入的 factoryProducer
为空,则会创建一个默认的工厂,当application
为空会返回NewInstanceFactory
,不为空则返回AndroidViewModelFactory
。这里根据源码我们知道application不为空,所以返回的是AndroidViewModelFactory
ViewModelLazy
public class ViewModelLazy<VM : ViewModel> (
private val viewModelClass: KClass<VM>,
private val storeProducer: () -> ViewModelStore,
private val factoryProducer: () -> ViewModelProvider.Factory
) : Lazy<VM> {
private var cached: VM? = null
override val value: VM
get() {
val viewModel = cached
return if (viewModel == null) {
val factory = factoryProducer()
val store = storeProducer()
ViewModelProvider(store, factory).get(viewModelClass.java).also {
cached = it
}
} else {
viewModel
}
}
...
}
首先,从缓存中获取 ViewModel。如果缓存中没有 ViewModel,则通过 ViewModelProvider + get
获取。这里我们主要看ViewModelProvider的get方法
ViewModelProvider
private val store: ViewModelStore,
@Suppress("UNCHECKED_CAST")
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
val viewModel = store[key]
// 不为空则返回viewmodel
...
return try {
factory.create(modelClass, extras)
} catch (e: AbstractMethodError) {
factory.create(modelClass)
}.also {
// 为空则创建不存到store中
store.put(key, it)
}
}
这里我们可以看到viewModel通过调用factory
的create
方法创建的,而factory是在Fragment调用createViewModelLazy
方式后创建的,类型是AndroidViewModelFactory
,它继承至NewInstanceFactory
,实现了Factory
的接口。
NewInstanceFactory
@Override
public T create() {
try {
return (T)myConstructor.newInstance(myArgs);
}
catch (Exception e) {
LOG.error(e);
return null;
}
}
这样就创建了一个ViewModel,并保存到store
中,因此,在创建 ViewModel 时,viewModels
首先从缓存中获取它。如果不在缓存中,则从 store
中获取。如果它不在 store
中,则重新创建它。相当于三级缓存。