弓背霞明剑照霜,秋风走马出咸阳。这篇文章主要讲述Android开发 ViewModel_2_了解多种的构建方式 (Factory 与 key)相关的知识,希望能为你提供帮助。
前言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 @MainThread public static ViewModelProvider of(@NonNull FragmentActivity activity) { return of(activity, null); }
恩,of又去调用了一个重载的of,但是传入了一个activity或者Fragment 和 一个null ,我们看看这个2个参数的of干了什么
@NonNull @MainThread public static ViewModelProvider 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 new ViewModelProvider(activity.getViewModelStore(), factory); }
我们可以看看ViewModelProvider.AndroidViewModelFactory.getInstance(application) 这行代码
private static AndroidViewModelFactory sInstance; /** * Retrieve a singleton instance of AndroidViewModelFactory. * * @param application an application to pass in {@link AndroidViewModel} * @return A valid {@link AndroidViewModelFactory} */ @NonNull public static AndroidViewModelFactory getInstance(@NonNull Application application) { if (sInstance == null) { sInstance = new AndroidViewModelFactory(application); } return sInstance; }
可以看到,直接给你了一个有Application的全局单例的Factory类。
接下来看看ViewModelProviders.of(getActivity()).get() get干了啥事 【Android开发 ViewModel_2_了解多种的构建方式 (Factory 与 key)】get()方法其实就是实现了 factory 创建 与 ViewModelStore保存 ViewModel,并且返回ViewModel。 我们可以看看下面这些代码
@NonNull @MainThread public < T extends ViewModel> T get(@NonNull Class< T> modelClass) { 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 @MainThread public < T extends ViewModel> T get(@NonNull String key, @NonNull Class< T> modelClass) { ViewModel viewModel = mViewModelStore.get(key); //去查找这个ViewModelStore 对应key的保存viewModelif (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 class ViewModelStore {private final HashMap< String, ViewModel> mMap = new HashMap< > (); final void put(String key, ViewModel viewModel) { ViewModel oldViewModel = mMap.put(key, viewModel); if (oldViewModel != null) { oldViewModel.onCleared(); } }final ViewModel get(String key) { return mMap.get(key); }Set< String> keys() { 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
推荐阅读
- appium---切换webview时报错
- Android 4.4 Init进程分析二(init.rc文件的解析)
- 点击微信内网页a标签,直接跳转打开淘宝APP的方法如此简单
- 移动app
- Appium超详细环境搭建for Mac
- android下载aosp镜像和开发板工程
- 安卓下pull解析
- 8-4 Flutter Android混合开发实战-调试与发布
- VS 2019开发APPlistview的应用