Android架构组件-ViewModel
在2017年谷歌推出Android新的架构组件-一组可以帮助开发者设计强大的,可测试的和可维护的应用程序组件库。
下面我将重点介绍以下几个实用组件:
LifeCycle
LiveData
ViewModel
--------------------------------------------------------------------
ViewModel
官网地址
处理状态
1、ViewModel是什么
ViewModel,从字面上理解的话,我们也能想到它肯定是跟视图(View)以及数据(Model)相关的。正像它字面意思一样,它是负责准备和管理和UI组件(Fragment/Activity)相关的数据类,也就是说ViewModel是用来管理UI相关的数据的。同时ViewModel还可以用来负责UI组件间的通信,这一点后面我们会有例子说明。
2、ViewModel能够做什么
- 保存(获取)数据
当Activity因为配置更改重新创建时,Activity必须重新获取数据。对于简单的数据,Activity可以使用 onSaveInstanceState()方法并从数据包中恢复其数据 ,但是此方法仅适用于可以序列化然后反序列化的少量数据,而不适用于潜在的大量数据,如用户列表或位图,而由于ViewModel贯穿了Activity的整个生命周期,且recreate时仍然存在,则可以用于保存/获取数据
- 异步获取数据
UI控制器经常需要进行异步调用,这可能需要一些时间才能返回。UI控制器需要管理这些调用,并确保系统在销毁后清理它们以避免潜在的内存泄漏或崩溃。而通过ViewModel,可以拥有跟随Activity或Fragment的生命周期,无需关心内存泄漏和崩溃。
- UI组件(Fragment)之间的通信
public class SharedViewModel extends ViewModel { private final MutableLiveData- selected = new MutableLiveData
- (); public void select(Item item) { selected.setValue(item); } public LiveData
- getSelected() { return selected; }}public class MasterFragment extends Fragment { private SharedViewModel model; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); itemSelector.setOnClickListener(item -> { model.select(item); }); }}public class DetailFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); model.getSelected().observe(this, item -> { // Update the UI. }); }}复制代码
3、ViewModel的基本使用
在LiveData中已经使用了ViewModel,大家不记得的可以回头去看 LiveData
4、ViewModel生命周期
先来看下官网的一张图
上图是用Activity作为例子,左侧表示Activity的生命周期状态,右侧绿色部分表示ViewModel的生命周期范围。当屏幕旋转的时候,Activity会被recreate,Activity会经过几个生命周期方法,但是这个时候ViewModel还是之前的对象,并没有被重新创建,只有当Activity的finish()方法被调用时,ViewModel.onCleared()方法会被调用,对象才会被销毁。这张图很好的描述了是当Activity被recreate时,ViewModel的生命周期。
另外,有个注意的地方:在ViewModel中不要持有Activity的引用。为什么要注意这一点呢?从上面的图我们看到,当Activity被recreate时,ViewModel对象并没有被销毁,如果Model持有Activity的引用时就可能会导致内存泄漏。那如果你要使用到Context对象怎么办呢,那就使用ViewModel的子类AndroidViewModel吧。
5、实现原理
类图
ViewModelProviders是ViewModel工具类,该类提供了通过Fragment和Activity得到ViewModel的方法,而具体实现又是有ViewModelProvider实现的。ViewModelProvider是实现ViewModel创建、获取的工具类。在ViewModelProvider中定义了一个创建ViewModel的接口类——Factory。ViewModelProvider中有个ViewModelStore对象,用于存储ViewModel对象。
ViewModelStore是存储ViewModel的类,具体实现是通过HashMap来保存ViewModle对象。
ViewModel是个抽象类,里面只定义了一个onCleared()方法,该方法在ViewModel不在被使用时调用。ViewModel有一个子类AndroidViewModel,这个类是便于要在ViewModel中使用Context对象,因为我们前面提到是不能在ViewModel中持有Activity的引用。
ViewModelStores是ViewModelStore的工厂方法类,它会关联HolderFragment,HolderFragment有个嵌套类——HolderFragmentManager。
时序图
在使用ViewModel的例子中,也许你会察觉得到一个ViewModel对象需要的步骤有点多啊,怎么不直接new一个出来呢?在你看到ViewModel的类图关系后,你应该就能明白了,因为是会缓存ViewModel对象的。下面以在Fragment中得到ViewModel对象为例看下整个过程的时序图。
时序图看起来比较复杂,但是它只描述了两个过程:
- 得到ViewModel对象。
- HolderFragment被销毁时,ViewModel收到onCleared()通知。
大家也可以结合时序图分析一下源码!
更多相关文章
- “罗永浩抖音首秀”销售数据的可视化大屏是怎么做出来的呢?
- Nginx系列教程(三)| 一文带你读懂Nginx的负载均衡
- 不吹不黑!GitHub 上帮助人们学习编码的 12 个资源,错过血亏...
- Android开发之Http通信HttpURLConnection接口
- android 将图片内容解析成字节数组,将字节数组转换为ImageView可
- Android伸手党系列之八:Android常用开发问题及经验分享
- android 自动生成html报表图片
- 舌尖上的Android(安卓)Volley(二)
- android 卡通片资源Tween动画