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 学习笔记相关推荐

  1. Android Jetpack Components of LiveData 学习笔记

    Android Jetpack Components of Lifecycle 学习笔记 Android Jetpack Components of LiveData 学习笔记 Android Jet ...

  2. Android Jetpack组件之ViewModel使用

    1.前言 最近简单看了下google推出的框架Jetpack,感觉此框架的内容可以对平时的开发有很大的帮助,也可以解决很多开发中的问题,对代码的逻辑和UI界面实现深层解耦,打造数据驱动型UI界面. A ...

  3. Android开源项目SlidingMenu本学习笔记(两)

    我们已经出台SlidingMenu使用:Android开源项目SlidingMenu本学习笔记(一个),接下来再深入学习下.依据滑出项的Menu切换到相应的页面 文件夹结构: 点击Bluetooth能 ...

  4. android spi读写不通,Android-SPI学习笔记

    概述 SPI(Service Provider Interface, 服务提供方接口),服务通常是指一个接口或者一个抽象类,服务提供方是对这个接口或者抽象类的具体实现,由第三方来实现接口提供具体的服务 ...

  5. Android Jetpack之DataBinding+ViewModel+LiveData+Room

    Android Jetpack之ViewModel.LiveData Android Jetpack之LifeCycle 前言 Jetpack是一个由多个技术库组成的套件,可帮助开发者遵循最佳做法,减 ...

  6. 《Android开发高手课》学习笔记

    最近在学习张绍文老师的<Android开发高手课>课程,学习到了很多的干货,特别是在处理问题的策略和知识的广度方面给了我很多的启发,对未来的学习也提供了方向. 目前,技术的发展有两个趋势. ...

  7. Android底层HAL驱动开发学习笔记

    2017.3.27 1.确定任务:加快摄像头的信息获取速率:缩减驱动程序.减小帧的大小,缩减一个像素点的比特流(6/8/10bit) 2.重点了解函数:camerabuffer *buffer=mPr ...

  8. Android Jetpack系列之ViewModel

    ViewModel介绍 ViewModel的定义:ViewModel旨在以注重生命周期的方式存储和管理界面相关的数据.ViewModel本质上是视图(View)与数据(Model)之间的桥梁,想想以前 ...

  9. Android推送进阶课程学习笔记

    今天在慕课网学习了Android进阶课程推送的server端处理回执的消息 . 这集课程主要介绍了,当server往client推送消息的时候,client须要发送一个回执回来确认收到了推送消息才算一 ...

最新文章

  1. 成功解决AttributeError: ‘NoneType‘ object has no attribute ‘shape‘
  2. shell脚本中if的相关参数
  3. 大厂首发:2021年Java工作或更难找
  4. 资深Android开发带你入门Framework,再不刷题就晚了!
  5. SuperAgent 中文乱码星号问号问题
  6. 二、RabbitMQ常用交换器
  7. atitit.atiHtmlUi web组件化方案与规范v1
  8. JavaWeb——JSP开发模型
  9. 使用google翻译免费翻译文档,这里以pdf为例
  10. 大学四年的最后一篇日志,致敬2012-2016那些似水流年
  11. 【C++决赛】2019年全国高校计算机能力挑战赛决赛C++组题解
  12. 牛顿迭代法 解 二元高次方程组 Mathematica
  13. 高德足迹地图在哪里_高德地图怎么点亮城市 足迹地图查看方法
  14. 03-word 中插入图片和表格
  15. 电商运营从哪些方面做数据分析?
  16. 写信中“敬启者”与“敬启”的区别
  17. python怎么表示不等于_Python关系运算符中表示“不等于”的是哪个?________
  18. VPP调试trace显示
  19. 人工智能——软科中国大学专业排名
  20. map中自定义比较函数

热门文章

  1. 不到千元月费,却能分享亿级爆炸式算力?
  2. css实现霓虹灯特效字体
  3. 华为助力,联发科营收创新高
  4. 杏树林诊所银川开业 打造“线上+线下”诊疗服务闭环
  5. A href中target属性的用法
  6. 64岁Python之父加盟微软!直言:“退休太无聊了”
  7. 戴尔笔记本键盘,fn+f1/fn+f2快捷键如何取消按fn键
  8. 联想的路与柳传志的功过
  9. 华为之后,谁能站上国产高端手机“C位”?
  10. Flink 第2章 状态及Checkpoint调优