内容简介:初到掘金,人生地不熟,喜欢的朋友,点个赞鼓励下新手呗~参考文章:https://developer.android.google.cn/topic/libraries/architecture/viewmodel
初到掘金,人生地不熟,喜欢的朋友,点个赞鼓励下新手呗~
参考文章:
https://developer.android.google.cn/topic/libraries/architecture/viewmodel
https://mp.weixin.qq.com/s/thoXHuXHC3sV90IFttHfXw
https://blog.csdn.net/gaugamela/article/details/56280384
ViewModel
类主要用来存储和管理与 UI
相关的数据,它能够让数据在屏幕旋转等配置信息改变导致 UI
重建的情况下不被销毁。
ViewModel生命周期
ViewModel
对象存活在系统中不被回收的时间是由创建 ViewModel
传递给 ViewModelProvider
的 Lifecycle
决定的。 ViewModel
将一直留在内存中,直到限定其存在时间范围的 Lifecycle
生命周期结束。对于 Activity
,是在Activity destroy时;而对于 Fragment
,是在Fragment detach时。
下图说明了 Activity
经历屏幕旋转直到最终destroyed掉这整个过程中所经历的各个生命周期。该图还在关联的 Activity
生命周期的旁边显示了 ViewModel
的生命周期。
我们可以看出, ViewModel
的生命周期贯穿 Activity
始终,直到 Activity
正常结束,并不会因为屏幕旋转等系统原因而导致 ViewModel
生命周期提前结束。同理 Fragment
对于 ViewModel
也一样。
本文,我们不讨论 ViewModel
的使用,而是直接分析它的原理。
ViewModel原理分析
我们分析源码的时候要带着明确目的带着问题去分析,从小见大,一个一个小问题解决,无头苍蝇似的扑进源码中,可能事倍功半。
在分析 ViewModel
源码之前,我们先介绍一下 ViewModel
组件中重要的几个类:
- ViewModel、 ViewModelProvider、 HolderFragment、 ViewModelStore
上面的类图简单地描述出了这几个类的作用以及关系,算是一个小概括,下面,我们直接进入源码分析它们具体的实现,以及它们是如何联系起来的。
(在这里默认大家已经知道了 ViewModel
的使用)我们知道ViewModel实例的创建是通过 ViewModelProviders.of(this).get(XxxViewModel.class)
生成的,这行代码可以分为两个步骤:
- 第一步:通过
ViewModelProviders.of(this)
生成ViewModelProvider
对象; - 第二步:通过
viewModelProvider.get(XxxViewModel.class)
生成相对ViewModel
对象。
下面我们的源码就针对这两个步骤分析一下 ViewModel
架构中重要的几个类。
ViewModelProvider
ViewModelProvider
是通过 ViewModelProviders.of(this)
生成的,我们进入源码看看:
public static ViewModelProvider of(@NonNull FragmentActivity activity) { return of(activity, null); } public static ViewModelProvider of(@NonNull FragmentActivity activity, @Nullable Factory factory) { Application application = checkApplication(activity); if (factory == null) { // 上面的类图,我们已经说了,生成 ViewModelProvider 实例的时候,如果 factory 传 null, // 系统会默认使用 AndroidViewModelFactory 作为 ViewModel 的生产类 factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application); } // 实例化创建一个 ViewModelProvider 对象返回 return new ViewModelProvider(ViewModelStores.of(activity), factory); }复制代码
可以看到, ViewModelProviders.of()
最终会 new
一个 ViewModelProvider
对象返回。在创建 ViewModelProvider
的时候,需要传入两个参数, ViewModelStore
以及 Factory
。在这里,我们先不讨论 ViewModelStores.of(activity)
是如何实例化返回 ViewModelStore
对象的,在后面,我们会说到。
先来看一下 Factory
类,它的定义很简单:
public interface Factory { // 只有一个 create 方法需要重写,这个方法就返回 ViewModel 对象, // 我们可以选择默认使用 AndroidViewModelFactory,也可以自定义 Factory <T extends ViewModel> T create(@NonNull Class<T> modelClass); }复制代码
当我们传入的factory参数为null的时候,会默认使用 AndroidViewModelFactory
:
public static class AndroidViewModelFactory extends ViewModelProvider.NewInstanceFactory { private static AndroidViewModelFactory sInstance; // 单例 @NonNull public static AndroidViewModelFactory getInstance(@NonNull Application application) { if (sInstance == null) { sInstance = new AndroidViewModelFactory(application); } return sInstance; } private Application mApplication; public AndroidViewModelFactory(@NonNull Application application) { mApplication = application; } @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { // 当 modelClass 类继承自 AndroidViewModel if (AndroidViewModel.class.isAssignableFrom(modelClass)) { //noinspection TryWithIdenticalCatches try { // 调用 modelClass 类中带有 Application 参数的构造方法创建一个 ViewMode 返回 return modelClass.getConstructor(Application.class).newInstance(mApplication); } catch (NoSuchMethodException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (InstantiationException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (InvocationTargetException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } // 如果 modelClass 类不是继承自 AndroidViewModel,调用 AndroidViewModelFactory 的 // 父类 NewInstanceFactory 的 onCreate 方法生成 ViewModel 对象返回 return super.create(modelClass); } }复制代码
AndroidViewModelFactory
的父类 NewInstanceFactory
也是非常简单:
public static class NewInstanceFactory implements Factory { @SuppressWarnings("ClassNewInstance") @NonNull @Override public <T extends ViewModel> T create(@NonNull Class<T> modelClass) { //noinspection TryWithIdenticalCatches try { // 直接通过反射调用 modelClass 类的无参构造函数实例化一个 ViewModel 对象返回 return modelClass.newInstance(); } catch (InstantiationException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } catch (IllegalAccessException e) { throw new RuntimeException("Cannot create an instance of " + modelClass, e); } } }复制代码
根据上面对 Factory
的分析, 在传入的factory参数为null的前提下 ,我们可以得出以下结论:
- 如果我们自定义的model继承自
ViewModel
,需要有一个默认无参的构造方法; - 如果我们自定义的model继承自
AndroidViewModel
,必须要有一个以Application
为唯一参数的构造函数。
当然我们也可以自定义 Factory
,在这里就不讨论了,广大聪明的读者才是最法力无边的~
ViewModelStore
上面我们知道了在构造 ViewModelProvider
的时候,会通过 ViewModelStores.of()
方法获取到一个 ViewModelStore
对象。 ViewModelStores
类是用于提供返回 ViewModelStore
对象的,下面我们来看看 ViewModelStores.of()
究竟做了什么?
public class ViewModelStores { private ViewModelStores() { } @NonNull @MainThread public static ViewModelStore of(@NonNull FragmentActivity activity) { // 开发者可以选择自己让 Activity 继承 ViewModelStoreOwner,然后实现 getViewModelStore 方法 if (activity instanceof ViewModelStoreOwner) { return ((ViewModelStoreOwner) activity).getViewModelStore(); } // holderFragmentFor(activity)方法返回继承了 ViewModelStoreOwner 的 HolderFragment 实例, // 调用这个 HolderFragment 对象的 getViewModelStore() 即可以拿到 ViewModelStore 实例。 return holderFragmentFor(activity).getViewModelStore(); } @NonNull @MainThread public static ViewModelStore of(@NonNull Fragment fragment) { // 同理,fragment 也可以继承 ViewModelStoreOwner ,实现 getViewModelStore 方法 if (fragment instanceof ViewModelStoreOwner) { return ((ViewModelStoreOwner) fragment).getViewModelStore(); } // 同上 return holderFragmentFor(fragment).getViewModelStore(); } }复制代码
可以看出, ViewModelStores.of()
方法主要就是从 ViewModelStoreOwner
对象中获取 ViewModelStore
对象。至于 holderFragmentFor()
方法究竟做了什么?我们下面在继续分析,现在,先看看 ViewModelStore
:
public class ViewModelStore { // 用 HashMap 存储 ViewModel 对象 private final HashMap<String, ViewModel> mMap = new HashMap<>(); // 新添 ViewModel final void put(String key, ViewModel viewModel) { // 如果对应 key 的 ViewModel 已经存在,那么覆盖它,并且调用它的 onCleared 方法 ViewModel oldViewModel = mMap.put(key, viewModel); if (oldViewModel != null) { oldViewModel.onCleared(); } } // 获取指定 key 的 ViewModel final ViewModel get(String key) { return mMap.get(key); } // 调用所有 ViewModel 的 onCleared 方法,并且清空整个 HashMap public final void clear() { for (ViewModel vm : mMap.values()) { vm.onCleared(); } mMap.clear(); } }复制代码
ViewModelStore
的实现很简单,主要的作用就是对 ViewModel
进行存储管理,通过一个 HashMap
保存了所有的 ViewModel
,分别通过 put
方法以及 get
方法添加和获取 ViewModel
,通过 clear
方法遍历调用所有 ViewModel
的 onCleared
方法并且清空map。
接下来,我们来看看最核心的一个类, HolderFragment
。
HolderFragment
前面我们分析 ViewModelStores.of()
方法的时候,提到过调用静态方法 holderFragmentFor()
方法能够返回一个继承了 ViewModelStoreOwner
的 HolderFragment
实例,现在我们就来看看 HolderFragment
这个类究竟是何方神圣?为什么当 Activity
由于屏幕旋转等被系统销毁时,这个 Fragment
实例也不会被销毁?
public class HolderFragment extends Fragment implements ViewModelStoreOwner { private static final String LOG_TAG = "ViewModelStores"; // 这是什么?请看下面注释分析 private static final HolderFragmentManager sHolderFragmentManager = new HolderFragmentManager(); @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public static final String HOLDER_TAG = "android.arch.lifecycle.state.StateProviderHolderFragment"; // 这就是我们存放 ViewModel 的 ViewModelStore,就定义在 HolderFragment里 private ViewModelStore mViewModelStore = new ViewModelStore(); public HolderFragment() { // 划重点啦!!!为什么当 activity 由于屏幕旋转等被系统销毁时, // 这个 fragment 实例也不会被销毁?因为设置了 setRetainInstance(true) setRetainInstance(true); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 当 Fragment 的 onCreate 方法执行,说明了 Fragment 已经成功添加到了 Activity, // sHolderFragmentManager 是 HolderFragmentManager类,它的 holderFragmentCreated()方法 // 是将该 Fragment 从 mNotCommittedActivityHolders 或 mNotCommittedFragmentHolders 中移除 // (HolderFragmentManager 的说明,请看下面的注释) sHolderFragmentManager.holderFragmentCreated(this); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } @Override public void onDestroy() { super.onDestroy(); // 当一个设置了 setRetainInstance(true) 的 Fragment 的 onDestroy 方法被调用, // 证明它依附的 Activity 已经寿终正寝,所以调用 mViewModelStore.clear(), // 前面我们已经说了,这个 clear 方法会调用所有 ViewModel 对象的 onCleared 方法 // 并且清空它们,我们可以在 ViewModel 的onCleared 方法做一些处理,以免起来不必要的 // 内存泄漏等问题 mViewModelStore.clear(); } // 该方法用于给外部调用,返回 ViewModelStore @Override public ViewModelStore getViewModelStore() { return mViewModelStore; } // 静态方法,没 ViewModelStores.of 方法中被调用 // 作用:在 activity 中添加一个 HolderFragment 用于存储存放了ViewModel对象的ViewModelStore public static HolderFragment holderFragmentFor(FragmentActivity activity) { return sHolderFragmentManager.holderFragmentFor(activity); } // 静态方法,没 ViewModelStores.of 方法中被调用 // 作用:在 fragment 中添加一个 HolderFragment 用于存储存放了ViewModel对象的ViewModelStore @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public static HolderFragment holderFragmentFor(Fragment fragment) { return sHolderFragmentManager.holderFragmentFor(fragment); } // 上面的大部分操作都是基于HolderFragmentManager,我们来分析下这个类 @SuppressWarnings("WeakerAccess") static class HolderFragmentManager { // 存放还没被系统正式添加到 Activity 中的 HolderFragment private Map<Activity, HolderFragment> mNotCommittedActivityHolders = new HashMap<>(); private Map<Fragment, HolderFragment> mNotCommittedFragmentHolders = new HashMap<>(); // 声明定义了一个能够感知 Activity 生命周期的 ActivityLifecycleCallbacks private ActivityLifecycleCallbacks mActivityCallbacks = new EmptyActivityLifecycleCallbacks() { @Override public void onActivityDestroyed(Activity activity) { // 当 Activity destroy 的时候,清除 mNotCommittedActivityHolders 中保存 // 的对应 HolderFragment。前面我们分析了 HolderFragment 的 onCreate 方法中 // 会请一次 mNotCommittedActivityHolders,为什么在这么还要多此一举呢?其实 // 并不是多此一举,因为 Fragment 有可能还没创建完,Activity 就夭折了,那这样子 // HodlerFragment 的 onCreate 就无法调用,所以在加多一层清理机制,确保能够 // 清除掉(不得不感叹,谷歌官方的严谨以及对源码的掌控理解能力) HolderFragment fragment = mNotCommittedActivityHolders.remove(activity); if (fragment != null) { Log.e(LOG_TAG, "Failed to save a ViewModel for " + activity); } } }; private boolean mActivityCallbacksIsAdded = false; private FragmentLifecycleCallbacks mParentDestroyedCallback = new FragmentLifecycleCallbacks() { @Override public void onFragmentDestroyed(FragmentManager fm, Fragment parentFragment) { // 与 mActivityCallbacks 的分析同理 super.onFragmentDestroyed(fm, parentFragment); HolderFragment fragment = mNotCommittedFragmentHolders.remove( parentFragment); if (fragment != null) { Log.e(LOG_TAG, "Failed to save a ViewModel for " + parentFragment); } } }; // HolderFragment 的 onCreate 生命周期被回调,就会调用这个方法,清除 // mNotCommittedActivityHolders 或者 mNotCommittedFragmentHolders 中 // 的引用的 HolderFragment void holderFragmentCreated(Fragment holderFragment) { Fragment parentFragment = holderFragment.getParentFragment(); if (parentFragment != null) { mNotCommittedFragmentHolders.remove(parentFragment); parentFragment.getFragmentManager().unregisterFragmentLifecycleCallbacks( mParentDestroyedCallback); } else { mNotCommittedActivityHolders.remove(holderFragment.getActivity()); } } private static HolderFragment findHolderFragment(FragmentManager manager) { if (manager.isDestroyed()) { throw new IllegalStateException("Can't access ViewModels from onDestroy"); } Fragment fragmentByTag = manager.findFragmentByTag(HOLDER_TAG); if (fragmentByTag != null && !(fragmentByTag instanceof HolderFragment)) { throw new IllegalStateException("Unexpected " + "fragment instance was returned by HOLDER_TAG"); } return (HolderFragment) fragmentByTag; } private static HolderFragment createHolderFragment(FragmentManager fragmentManager) { HolderFragment holder = new HolderFragment(); fragmentManager.beginTransaction().add(holder, HOLDER_TAG).commitAllowingStateLoss(); return holder; } HolderFragment holderFragmentFor(FragmentActivity activity) { FragmentManager fm = activity.getSupportFragmentManager(); HolderFragment holder = findHolderFragment(fm); if (holder != null) { return holder; } holder = mNotCommittedActivityHolders.get(activity); if (holder != null) { return holder; } if (!mActivityCallbacksIsAdded) { mActivityCallbacksIsAdded = true; activity.getApplication().registerActivityLifecycleCallbacks(mActivityCallbacks); } holder = createHolderFragment(fm); // 我们新添加 add 的 Fragment 并不会马上就执行添加完(也就是说,这个方法执行完成后,马上再 // 调用一次,上面的 findHolderFragment 会返回 null。但是这没有关系,因为接下来我们还可 // 从 mNotCommittedActivityHolders 获取到对应的实例),所以我们这里先把他放在 // mNotCommittedActivityHolders 中。Not Committed 表示 fragment 的 commit 还没有完成 mNotCommittedActivityHolders.put(activity, holder); return holder; } HolderFragment holderFragmentFor(Fragment parentFragment) { FragmentManager fm = parentFragment.getChildFragmentManager(); HolderFragment holder = findHolderFragment(fm); if (holder != null) { return holder; } holder = mNotCommittedFragmentHolders.get(parentFragment); if (holder != null) { return holder; } parentFragment.getFragmentManager().registerFragmentLifecycleCallbacks(mParentDestroyedCallback, false); holder = createHolderFragment(fm); // 同上 mNotCommittedFragmentHolders.put(parentFragment, holder); return holder; } } }复制代码
通过上面的注释,我们已经详细地对 HolderFragment
这个核心类做了分析,总结一下:
-
HolderFragment
通过设置setRetainInstance(true)
,使得自身能够不受到屏幕旋转等configuration changes影响而存活,直到依附的Activity
正常结束。 - 因为
HolderFragment
的生命周期,ViewModelStore
对象保存在HolderFragment
中,而ViewModel
又存储在ViewModelStore
中,这就是为什么我们说ViewModel
类能够让数据在屏幕旋转等配置信息改变导致UI重建的情况下不被销毁。
总结
ViewModel
的分析就到此为止了,我们主要解决了两个问题:
- ViewModel是怎样创建的?
通过调用 ViewModelProviders.of(this).get(XxxViewModel.class)
或者 ViewModelProviders.of(this, mFactory).get(XxxViewModel.class)
返回 ViewModel
。最终 ViewModel
实际上是由 Factory
创建,当我们不传 Factory
参数时,系统默认使用 AndroidViewModelFactory
作为 Factory
,通过反射生成 ViewModel
实例对象返回。
- ViewModel以及存储在其中的数据是怎样在屏幕旋转下依然保留在内存中的?
GC垃圾回收机制不会回收被强引用的对象。在开发过程中,我们需要存储的数据被 ViewModel
引用, ViewModel
被 ViewModelStore
引用,而 ViewModelStore
又被 HolderFragment
引用,于是就形成了一条引用链: HolderFragment
-> ViewModelStore
-> ViewModel
->我们想要存储的数据(最佳实践是 LiveData
)。通过上面 HolderFragment
的分析,我们知道 HodlerFragment
在创建时,设置了 setRetainInstance(true)
,因此它使得自身能够不受到屏幕旋转等configuration changes影响而存活,直到依附的 Activity
正常结束。
最后,附上一副时序图供诸位朋友们帮助理解记忆:
以上所述就是小编给大家介绍的《Android 官方架构组件(三)——ViewModel》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MVVM 架构解析及 Jetpack 架构组件的使用
- MVVM 架构解析及 Jetpack 架构组件的使用
- 微服务架构————基本组件
- 组件化架构漫谈
- Rabbitmq基础组件架构设计
- Android组件化入门:一步步搭建组件化架构
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。