Android Jetpack Components of ViewModel 学习笔记
Android Jetpack Components of Lifecycle 学习笔记
Android Jetpack Components of LiveData 学习笔记
Android Jetpack Components of ViewModel 学习笔记
Demo 地址:https://github.com/mengzhinan/Lifecycle_LiveData_ViewModel_demo
ViewModel Google 文档:https://developer.android.google.cn/topic/libraries/architecture/viewmodel
环境配置:
与 Lifecycle 和 LiveData 略有不同,在其基础上,还需要导入依赖:
// viewmodel 需要添加的配置
implementation 'android.arch.lifecycle:extensions:1.1.1'
ViewModel 是什么?
ViewModel 类的设计目的是以生命周期意识的方式存储和管理与UI相关的数据。ViewModel 类允许数据在配置更改(如屏幕旋转)中生存。
以我的理解总结为:
1、ViewModel 可以实现在同一个 Activity 对象下的多个 Fragment 之间数据共享。
2、ViewModel 可以实现在手机屏幕旋转前后数据共享,避免不必要的重复数据请求。
先从 Demo 使用看起吧。还是上一篇文章的 LiveData Demo:
public class DataUtil {private MutableLiveData<String> name = new MutableLiveData<>();public LiveData<String> getNameLiveData(){return name;}public void requestHead() {// 模拟请求网络或 DB,然后更新数据name.setValue("requestHead success");}public void requestList() {// 模拟请求网络或 DB,然后更新数据name.setValue("requestList success");}}
public class LiveDataActivity extends AppCompatActivity {private DataUtil dataUtil;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);dataUtil = new DataUtil();dataUtil.getNameLiveData().observe(this, data -> {// 得到数据更新});}@Overrideprotected void onResume() {super.onResume();dataUtil.requestHead();dataUtil.requestList();}
}
上面代码其实有个问题,如果 DataUtil 重复创建的话,将会对应的重新创建 MutableLiveData 对象,故无法实现数据共享。先别钻牛角,看 ViewModel 的用法:
public class ListViewModel extends ViewModel {private MutableLiveData<String> headLiveData;private MutableLiveData<String> listLiveData;public LiveData<String> getHeadLiveData() {if (headLiveData == null) {headLiveData = new MutableLiveData<>();}return headLiveData;}public LiveData<String> getListLiveData() {if (listLiveData == null) {listLiveData = new MutableLiveData<>();}return listLiveData;}public void requestHead() {// TODO: 2019-07-29headLiveData.setValue("head request success");}public void requestList() {// TODO: 2019-07-29listLiveData.setValue("list request success");}
}
public class ViewModelActivity extends AppCompatActivity {private ListViewModel listViewModel;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);listViewModel = ViewModelProviders.of(this).get(ListViewModel.class);listViewModel.getHeadLiveData().observe(this, data->{// 头部数据更新});listViewModel.getListLiveData().observe(this, data->{// list 数据更新});}@Overrideprotected void onResume() {super.onResume();listViewModel.requestHead();listViewModel.requestList();}
}
代码说明:
DataUtil 逻辑更改为了 ListViewModel,然后继承了 ViewModel 类。其他的没有本质变化。
在 ViewModelActivity 中,唯一的变化是 ListViewModel 的创建方式变为了:
listViewModel = ViewModelProviders.of(this).get(ListViewModel.class);
我们先来分析 ViewModel 类:
public abstract class ViewModel {/*** This method will be called when this ViewModel is no longer used and will be destroyed.* <p>* It is useful when ViewModel observes some data and you need to clear this subscription to* prevent a leak of this ViewModel.*/@SuppressWarnings("WeakerAccess")protected void onCleared() {}
}
这是一个抽象类,其中只有一个方法 onCleared(),当 ViewModel 所在的 Activity 销毁时,回调此方法清理资源。
ViewModel 有一个比较常用的子类 AndroidViewModel,提供 application 对象:
/*** Application context aware {@link ViewModel}.* <p>* Subclasses must have a constructor which accepts {@link Application} as the only parameter.* <p>*/
public class AndroidViewModel extends ViewModel {@SuppressLint("StaticFieldLeak")private Application mApplication;public AndroidViewModel(@NonNull Application application) {mApplication = application;}/*** Return the application.*/@SuppressWarnings("TypeParameterUnusedInFormals")@NonNullpublic <T extends Application> T getApplication() {//noinspection uncheckedreturn (T) mApplication;}
}
我们再回头分析 ViewModel 获取的方法:
ViewModelProviders.of(this).get(ListViewModel.class);
先追查 get() 方法:
@NonNull@MainThreadpublic <T extends ViewModel> T get(@NonNull Class<T> modelClass) {String canonicalName = modelClass.getCanonicalName();if (canonicalName == null) {throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");}return get(DEFAULT_KEY + ":" + canonicalName, modelClass);}
继续追查 get() 重载方法:
@NonNull@MainThreadpublic <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {ViewModel viewModel = mViewModelStore.get(key);if (modelClass.isInstance(viewModel)) {//noinspection uncheckedreturn (T) viewModel;} else {//noinspection StatementWithEmptyBodyif (viewModel != null) {// TODO: log a warning.}}viewModel = mFactory.create(modelClass);mViewModelStore.put(key, viewModel);//noinspection uncheckedreturn (T) viewModel;}
如果传递的 ViewModel 已经缓存了,则把缓存的 ViewModel 对象直接返回;否则才创建新的对象。
那么 mViewModelStore 是如何做到缓存的呢?
public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {mFactory = factory;this.mViewModelStore = store;}
发现 mViewModelStore 是在 ViewModelProvider 的构造函数中赋值的。追查到 ViewModelProviders 的 of 方法中:
@NonNull@MainThreadpublic static ViewModelProvider of(@NonNull FragmentActivity activity,@Nullable Factory factory) {Application application = checkApplication(activity);if (factory == null) {factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);}return new ViewModelProvider(ViewModelStores.of(activity), factory);}
追索到 ViewModelStores 的 of 方法:
@NonNull@MainThreadpublic static ViewModelStore of(@NonNull FragmentActivity activity) {if (activity instanceof ViewModelStoreOwner) {return ((ViewModelStoreOwner) activity).getViewModelStore();}return holderFragmentFor(activity).getViewModelStore();}
找到 HolderFragment 中的 holderFragmentFor() 方法:
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)public static HolderFragment holderFragmentFor(FragmentActivity activity) {return sHolderFragmentManager.holderFragmentFor(activity);}
其实看到这儿,基本可以看出原理:
在 Activity 中创建一个 HolderFragment 对象,并添加到 FragmentManager 中。在 HolderFragment 中保存 ViewModel 集合。
因此,当 Activity 销毁时,也会同步销毁 HolderFragment。
那为什么说手机屏幕旋转前后,ViewModel 不会销毁呢?
追查代码,HolderFragment 类的构造函数:
public HolderFragment() {setRetainInstance(true);}
setRetainInstance(true); 这行代码应该是设置避免在屏幕旋转时重建 Fragment。
所以,总结 ViewModel 的特点:
ViewModel 是依附 HolderFragment 保存在 Activity 的 FragmentManager 中的。在同一个 Activity 下的任意位置、任意 Fragment 中通过 ViewModelProviders.of(this).get(xxx) 方式获取 ViewModel,都会是同一个对象,故避免了重复请求,实现数据共享。
由于 HolderFragment 的特点,可避免屏幕旋转后的数据丢失,避免重复请求。
Demo 地址:https://github.com/mengzhinan/Lifecycle_LiveData_ViewModel_demo
Android Jetpack Components of ViewModel 学习笔记相关推荐
- Android Jetpack Components of LiveData 学习笔记
Android Jetpack Components of Lifecycle 学习笔记 Android Jetpack Components of LiveData 学习笔记 Android Jet ...
- Android Jetpack组件之ViewModel使用
1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...
- Android开源项目SlidingMenu本学习笔记(两)
我们已经出台SlidingMenu使用:Android开源项目SlidingMenu本学习笔记(一个),接下来再深入学习下.依据滑出项的Menu切换到相应的页面 文件夹结构: 点击Bluetooth能 ...
- android spi读写不通,Android-SPI学习笔记
概述 SPI(Service Provider Interface, 服务提供方接口),服务通常是指一个接口或者一个抽象类,服务提供方是对这个接口或者抽象类的具体实现,由第三方来实现接口提供具体的服务 ...
- Android Jetpack之DataBinding+ViewModel+LiveData+Room
Android Jetpack之ViewModel.LiveData Android Jetpack之LifeCycle 前言 Jetpack是一个由多个技术库组成的套件,可帮助开发者遵循最佳做法,减 ...
- 《Android开发高手课》学习笔记
最近在学习张绍文老师的<Android开发高手课>课程,学习到了很多的干货,特别是在处理问题的策略和知识的广度方面给了我很多的启发,对未来的学习也提供了方向. 目前,技术的发展有两个趋势. ...
- Android底层HAL驱动开发学习笔记
2017.3.27 1.确定任务:加快摄像头的信息获取速率:缩减驱动程序.减小帧的大小,缩减一个像素点的比特流(6/8/10bit) 2.重点了解函数:camerabuffer *buffer=mPr ...
- Android Jetpack系列之ViewModel
ViewModel介绍 ViewModel的定义:ViewModel旨在以注重生命周期的方式存储和管理界面相关的数据.ViewModel本质上是视图(View)与数据(Model)之间的桥梁,想想以前 ...
- Android推送进阶课程学习笔记
今天在慕课网学习了Android进阶课程推送的server端处理回执的消息 . 这集课程主要介绍了,当server往client推送消息的时候,client须要发送一个回执回来确认收到了推送消息才算一 ...
最新文章
- 成功解决AttributeError: ‘NoneType‘ object has no attribute ‘shape‘
- shell脚本中if的相关参数
- 大厂首发:2021年Java工作或更难找
- 资深Android开发带你入门Framework,再不刷题就晚了!
- SuperAgent 中文乱码星号问号问题
- 二、RabbitMQ常用交换器
- atitit.atiHtmlUi web组件化方案与规范v1
- JavaWeb——JSP开发模型
- 使用google翻译免费翻译文档,这里以pdf为例
- 大学四年的最后一篇日志,致敬2012-2016那些似水流年
- 【C++决赛】2019年全国高校计算机能力挑战赛决赛C++组题解
- 牛顿迭代法 解 二元高次方程组 Mathematica
- 高德足迹地图在哪里_高德地图怎么点亮城市 足迹地图查看方法
- 03-word 中插入图片和表格
- 电商运营从哪些方面做数据分析?
- 写信中“敬启者”与“敬启”的区别
- python怎么表示不等于_Python关系运算符中表示“不等于”的是哪个?________
- VPP调试trace显示
- 人工智能——软科中国大学专业排名
- map中自定义比较函数