ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据,ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
那么我们今天就探索下,配置更改后,是如何继续留存数据的。
首先我们看下如何创建ViewModel
实例:
class CustomFactory : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return when (modelClass) {
MainViewModel::class.java -> {
MainViewModel()
}
else -> throw IllegalArgumentException("Unknown class $modelClass")
} as T
}
}
创建ViewModel
实例
// 1
val viewModelProvider = ViewModelProvider(this, CustomFactory())
// 2
val viewModel: MainViewModel= viewModelProvider.get(MainViewModel::class.java)
// 或者使用KTX来创建
//val model : MainViewModel by viewModels { CustomFactory() }
ViewModelProvider
源码
public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull ViewModelProvider.Factory factory) {
// 3
this(owner.getViewModelStore(), factory);
}
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull ViewModelProvider.Factory factory) {
this.mFactory = factory;
this.mViewModelStore = store;
}
ViewModelStoreOwner
源码
public interface ViewModelStoreOwner {
@NonNull
ViewModelStore getViewModelStore();
}
看看上面这段代码做了什么:
-
首先创建一个ViewModelProvider实例,
ViewModelProvider
构造函数的第一个参数是ViewModelStoreOwner
,那为什么可以传入Activity
实例呢,是因为ComponentActivity
实现了ViewModelStoreOwner
这个接口; -
通过
get(@NonNull Class<T> modelClass)
方法 获取到ViewModel
的实例; -
通过
owner.getViewModelStore()
获取到ViewModelStore
,也就是ComponentActivity
的getViewModelStore()
方法。
然后我们看下ViewModelProvider#get()
方法:
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
String canonicalName = modelClass.getCanonicalName();
if (canonicalName == null) {
throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
} else {
return this.get("androidx.lifecycle.ViewModelProvider.DefaultKey:" + canonicalName, modelClass);
}
}
@NonNull
@MainThread
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
ViewModel viewModel = this.mViewModelStore.get(key);
if (modelClass.isInstance(viewModel)) {
if (this.mFactory instanceof ViewModelProvider.OnRequeryFactory) {
((ViewModelProvider.OnRequeryFactory)this.mFactory).onRequery(viewModel);
}
return viewModel;
} else {
if (viewModel != null) {
}
if (this.mFactory instanceof ViewModelProvider.KeyedFactory) {
viewModel = ((ViewModelProvider.KeyedFactory)this.mFactory).create(key, modelClass);
} else {
viewModel = this.mFactory.create(modelClass);
}
this.mViewModelStore.put(key, viewModel);
return viewModel;
}
}
从在上面的代码中可以发现,ViewModelStore
中持有一个HashMap
,如果ViewModelStore
中有缓存的ViewModel
实例,就直接返回,否则创建新的实例并存入到ViewModelStore
中。
接下来我们看下 ComponentActivity#getViewModelStore()
方法:
@NonNull
public ViewModelStore getViewModelStore() {
if (this.getApplication() == null) {
throw new IllegalStateException("Your activity is not yet attached t