内容简介:初到掘金,人生地不熟,喜欢的朋友,点个赞鼓励下新手呗~参考文章: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组件化入门:一步步搭建组件化架构
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Linux Command Line
William E. Shotts Jr. / No Starch Press, Incorporated / 2012-1-17 / USD 39.95
You've experienced the shiny, point-and-click surface of your Linux computer-now dive below and explore its depths with the power of the command line. The Linux Command Line takes you from your very ......一起来看看 《The Linux Command Line》 这本书的介绍吧!
html转js在线工具
html转js在线工具
RGB CMYK 转换工具
RGB CMYK 互转工具