viewmodel创建及使用分析
1、相关的类
- ViewModelStore :管理viewModel实例,内部包含一个Map用来存储viewmodel,内部包括put、get、clear等方法
- ViewModelProvider :管理ViewModelStore和Factory,Factory里面有create方法是创建对应的viewmodel的,ViewModelProvider内部有一个get方法获取viewmodel
2、在项目中应用
首先新建项目分别创建TestViewModel
TestViewModel.class
fun provideFactory(
repository: TestRepository
): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return TestViewModel(repository) as T
}
}
MainActivity.class中初始化代码:
private val testViewModel by viewModels<TestViewModel> {
TestViewModel.provideFactory(TestRepository())
}
接下来在MainActivity里面就可以正常使用这个viewmodel了
3、流程简单解析
首先我们在mainActivity里面初始化时候使用了by viewmodel 这个方式进行初始化点击进入这个方法之后源码如下:
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
noinline extrasProducer: (() -> CreationExtras)? = null,
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
defaultViewModelProviderFactory
}
return ViewModelLazy(
VM::class,
{ viewModelStore },
factoryPromise,
{ extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras }
)
}
可以看到viewModels是ComponentActivity的一个扩展函数,参数需要传factoryProducer,factoryProducer就是前面我们提到过的ViewModelProvider的内部的一个factory类,用来创建viewModel的,所以我们传入TestViewModel.provideFactory。
继续向下看进入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
override val value: VM
get() {
val viewModel = cached
return if (viewModel == null) {
val factory = factoryProducer()
val store = storeProducer()
ViewModelProvider(
store,
factory,
extrasProducer()
).get(viewModelClass.java).also {
cached = it
}
} else {
viewModel
}
}
override fun isInitialized(): Boolean = cached != null
}
首先判断是否有缓存,如果有缓存直接返回,无缓存情况下就去ViewModelProvider获取对应的viewmodel并且进行一下缓存操作,接下来我们看一下ViewModelProvider的get方法
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
val viewModel = store[key]
if (modelClass.isInstance(viewModel)) {
(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
// 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)
} catch (e: AbstractMethodError) {
factory.create(modelClass)
}.also { store.put(key, it) }
}
get方法通过内部的store传入类名来获取view model,那么store是从哪里来的呢?往回看能看到是在ComponentActivity.viewModels这里返回了一个ViewModelLazy时传入了viewModelStore,这个viewModelStore是从ComponentActivity初始化时候就创建了的
public ComponentActivity() {
//......
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();
}
mReportFullyDrawnExecutor.activityDestroyed();
}
}
});
getLifecycle().addObserver(new LifecycleEventObserver() {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
ensureViewModelStore();
getLifecycle().removeObserver(this);
}
});
//......
}
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创建时添加生命周期监听,生命周期变更时创建ViewModelStore,当生命周期destory时会通过isChangingConfigurations来判断是否是通过切换横竖屏导致的destroy,如果是的话不会对view model执行clear,这样保证了view model在切换横竖屏时依然可以保存数据,等页面真正的退出执行的destroy时才会对viewmodel执行clear方法,这样保证了viewmodel的生命周期和activity一致,也不需要我们单独对其生命周期进行维护。
针对这个流程简单的分析,如有分析不符的地方欢迎评论指正
原文地址:https://blog.csdn.net/qq_41167962/article/details/140315714
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!