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? = nulloverride val value: VMget() {val viewModel = cachedreturn 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() {@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {if (event == Lifecycle.Event.ON_DESTROY) {// Clear out the available contextmContextAwareHelper.clearAvailableContext();// And clear the ViewModelStoreif (!isChangingConfigurations()) {getViewModelStore().clear();}mReportFullyDrawnExecutor.activityDestroyed();}}});getLifecycle().addObserver(new LifecycleEventObserver() {@Overridepublic 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 NonConfigurationInstancesmViewModelStore = nc.viewModelStore;}if (mViewModelStore == null) {mViewModelStore = new ViewModelStore();}}}
在activity创建时添加生命周期监听,生命周期变更时创建ViewModelStore,当生命周期destory时会通过isChangingConfigurations来判断是否是通过切换横竖屏导致的destroy,如果是的话不会对view model执行clear,这样保证了view model在切换横竖屏时依然可以保存数据,等页面真正的退出执行的destroy时才会对viewmodel执行clear方法,这样保证了viewmodel的生命周期和activity一致,也不需要我们单独对其生命周期进行维护。
针对这个流程简单的分析,如有分析不符的地方欢迎评论指正