前言
ViewModel的虽然可以以很简单的ViewModelProviders.of(getActivity()).get(ViewModel.class); 但是这只是google提供的简单构建,你需要引入下面的库才能使用:
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
但是!远远不止这样。ViewModel还可以自定义实例(其实自己实现实例构建ViewModel才是google推荐的,但是每次都要创建构建类非常麻烦,这些后面会提到)方式或者增加key来创建多个不同的ViewModel。
了解ViewModel的构建原理
因为后续的使用ViewModelProvider.Factory创建ViewModel,所以我们必需了解一些些ViewModel构建、保存、移除原理。好在有一个参照物可以阅读理解,那就是上面提到以ViewModelProviders形式的构建ViewModel。对照着它看基本上就能明白一些东西了。
看看 ViewModelProviders.of() 干了啥事情
我们点击进入源码后可以看到如下代码
@NonNull
@MainThreadpublic staticViewModelProvider of(@NonNull FragmentActivity activity) {return of(activity, null);
}
恩,of又去调用了一个重载的of,但是传入了一个activity或者Fragment 和 一个null ,我们看看这个2个参数的of干了什么
@NonNull
@MainThreadpublic staticViewModelProvider of(@NonNull FragmentActivity activity,
@Nullable Factory factory) {
Application application= checkApplication(activity); //源码在这里检查了一下activity的application
if (factory == null) {//它拿application去创建了一个Factory类//这个factory其实就是构建ViewModel的工厂类
factory =ViewModelProvider.AndroidViewModelFactory.getInstance(application);
}//实例化了一个ViewModelProvider,//在activity里取得ViewModelStore(这个东西是用于保存ViewModel使用的),也传入了//并且也把Factory类一起传入//其实ViewModelStore和factory传入后就直接成为成员变量缓存了,等待你调用get方法来创建ViewModel
return newViewModelProvider(activity.getViewModelStore(), factory);
}
我们可以看看ViewModelProvider.AndroidViewModelFactory.getInstance(application) 这行代码
private staticAndroidViewModelFactory sInstance;/*** Retrieve a singleton instance of AndroidViewModelFactory.
*
*@paramapplication an application to pass in {@linkAndroidViewModel}
*@returnA valid {@linkAndroidViewModelFactory}*/@NonNullpublic staticAndroidViewModelFactory getInstance(@NonNull Application application) {if (sInstance == null) {
sInstance= newAndroidViewModelFactory(application);
}returnsInstance;
}
可以看到,直接给你了一个有Application的全局单例的Factory类。
接下来看看ViewModelProviders.of(getActivity()).get() get干了啥事
get()方法其实就是实现了factory 创建 与 ViewModelStore保存 ViewModel,并且返回ViewModel。 我们可以看看下面这些代码
@NonNull
@MainThreadpublic T get(@NonNull ClassmodelClass) {
String canonicalName= modelClass.getCanonicalName(); //获取了传入的实现的ViewModel的类名
if (canonicalName == null) {throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
}//因为我们没有传入key,所以这里直接用类名取代的成为了key//然后就进入下面这个重载的get方法里进行实现了
return get(DEFAULT_KEY ":" canonicalName, modelClass);
}
@NonNull
@MainThreadpublic T get(@NonNull String key, @NonNull ClassmodelClass) {
ViewModel viewModel= mViewModelStore.get(key);//去查找这个ViewModelStore 对应key的保存viewModel
if (modelClass.isInstance(viewModel)) { //检查一下这个viewModel是不是已经实例化,不是null//noinspection unchecked
return (T) viewModel; //如果已经实例化,不等于null就直接返回
} else{//noinspection StatementWithEmptyBody
if (viewModel != null) {//TODO: log a warning.
}
}//下面就用传入的Factory类来实例化你需要的ViewModel
if (mFactory instanceof KeyedFactory) { //这里检查是不是带key
viewModel =((KeyedFactory) (mFactory)).create(key, modelClass);
}else{
viewModel=(mFactory).create(modelClass);
}
mViewModelStore.put(key, viewModel);//然后存一下ViewModel//noinspection unchecked
return (T) viewModel; //返回viewModel
}
移除缓存的ViewModel
其实蛛丝马迹就在ViewModelStore里
public classViewModelStore {private final HashMap mMap = new HashMap<>();final voidput(String key, ViewModel viewModel) {
ViewModel oldViewModel=mMap.put(key, viewModel);if (oldViewModel != null) {
oldViewModel.onCleared();
}
}finalViewModel get(String key) {returnmMap.get(key);
}
Setkeys() {return new HashSet<>(mMap.keySet());
}/*** Clears internal storage and notifies ViewModels that they are no longer used.*/
public final void clear() { //这里清理了当前Activity或者Fragment的所有ViewModel,这个方法是在Activity或者Fragment在销毁的时候有调用的
for(ViewModel vm : mMap.values()) {
vm.clear();
}
mMap.clear();
}
}
自己实现ViewModelProvider.Factory
对于key的使用
End