学会使用 LiveData 和 ViewModel,我相信会让你在写业务时变得轻松🌞
前言:
本文不定时更新,有问题欢迎在评论区提出~
最近更新时间:2022-06-21
介绍
在 2017 年,那时,观察者模式有效的简化了开发,但是诸如 RxJava 一类的库有一些太过复杂,学习成本太高,为此,LiveData 出现了,一个专用于 Android 的,具备自主生命周期感知能力的,可观测的数据存储类。同时也出现了 ViewModel 这个组件,配合 LiveData,更方便的实现 MVVM 模式中 Model 与 View 的分离。那么就让本文来带大家来学习 LiveData 与 ViewModel 的使用吧。
LiveData 和 ViewModel 的关系:
本文的案例代码:https://github.com/taxze6/Jetpack_learn/tree/main/Jetpack_basic_learn/livedata_viewmodel
LiveData
参考资料:
🌟官方文档:https://developer.android.google.cn/topic/libraries/architecture/livedata
🌟LiveData postValue 详解:https://www.cnblogs.com/button123/p/14871526.html
LiveData 是一种可观察的数据存储器类(响应式编程,类似 Vue)。与常规的可观察类不同,LiveData 具有生命周期感知能力。LiveData 最重要的是它了解观察者的生命周期,如 Activity 和 Fragment。
因此,当 LiveData 发送变化时,UI 会收到通知,然后 UI 可以使用新数据重新绘制自己。换句话说,LiveData 可以很容易地使屏幕上发生的事情与数据保持同步(响应式编程的核心)
使用 LiveData 具有以下优势:
UI 与数据状态匹配
LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知
Observer
对象。您可以整合代码以在这些Observer
对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。提高代码的稳定性
代码稳定性在整个应用程序生命周期中增加:
活动停止时不会发生崩溃。如果应用程序组件处于非活动状态,则这些更改不受影响。因此,您在更新数据时无需担心应用程序组件的生命周期。对于后台堆栈中的活动,它不会接受任何 LiveData 事件
内存泄漏会减少,观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理
取消订阅任何观察者时无需担心
如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
不再需要手动处理生命周期
界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
数据始终保持最新状态
如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
共享资源
像单例模式一样,我们也可以扩展我们的 LiveData 对象来包装系统服务,以便它们可以在我们的应用程序中共享。一旦 LiveData 对象连接到系统服务,任何需要资源的观察者可以轻松地观看 LiveData 对象。
在以下情况中,不要使用 LiveData:
您需要在信息上使用大量运算符,尽管 LiveData 提供了诸如转换之类的工具,但只有 Map 和 switchMap 可以帮助您
您没有与信息的 UI 交互
您有一次性的异步操作
您不必将缓存的信息保存到 UI 中
如何使用 LiveData
一般来说我们会在 ViewModel 中创建 Livedata 对象,保证 app 配置变更时,数据不会丢失,然后再 Activity/Fragment 的 onCreate 中注册 Livedata 监听(因为在 onStart 和 onResume 中进行监听可能会有冗余调用)
基础使用流程:
1.创建一个实例 LiveData 来保存某种类型的数据。一般在你创建的 ViewModel 类中完成
2.在 Activity 或者 Fragment 中获取到 ViewModel,通过 ViewModel 获取到对应的 LiveData
3.给 LiveData 添加观察者监听,用来监听 LiveData 中的数据变化,在 Observer 的 onChanged 中使用监听回调数据
进阶用法:
Transformations.map
现在有一个场景:我们通过网络请求,获得了一个 User 类数据(LiveData),但是,我们只想把 User.name 暴露给外部观察者,这样我们就可以通过 Transformations.map 来转化 LiveData 的数据类型,从而来实现上述场景。这个函数常用于对数据的封装。
Transformations.switchMap
switchMap 是根据传入的 LiveData 的值,然后判断这个值,然后再去切换或者构建新的 LiveData。比如我们有些数据需要依赖其他数据进行查询,就可以使用 switchMap。
例如,有一个学生,他有两门课程的成绩,但是在 UI 组件中,我们一次只能显示一门课的成绩,在这个需要判断展示哪门课程成绩的需求下,我们就可以使用 switchMap。
MediatorLiveData
MediatorLiveData 继承于 MutableLiveData,在 MutableLiveData 的基础上,增加了合并多个 LiveData 数据源的功能。其实就是通过 addSource()这个方法去监听多个 LiveData。
例如:现在有一个存在本地的 dbLiveData,还有一个网络请求来的 LiveData,我们需要讲上面两个结果结合之后展示给用户,第一种做法是我们在 Activity 中分别注册这两个 LiveData 的观察者,当数据发生变化时去更新 UI,但是我们其实使用 MediatorLiveData 可以简化这个操作。
解释:
如果是第一次接触到 LiveData 的朋友可能会发现,我们虽然一直在提 LiveData,但是用的时候却是 MutableLiveData,这两个有什么关系呢,既然都没怎么用 LiveData,那么把标题直接改成 MutableLiveData 吧其实,LiveData 与 MutableLiveData 在概念上是一模一样的。唯一的几个区别分别是:
💡“此处引用:LiveData与MutableLiveData的区别文章中的段落”
MutableLiveData 的父类是 LiveData
LiveData 在实体类里可以通知指定某个字段的数据更新
MutableLiveData 则是完全是整个实体类或者数据类型变化后才通知.不会细节到某个字段。
原理探究:
对于 LiveData 的基础使用我们就讲到这里,想要探索 LiveData 原理的朋友可以从下面几个角度:
LiveData 的工作原理
LiveData 的 observe 方法源码分析
LifecycleBoundObserver 源码分析
activeStateChanged 源码分析(用于粘性事件)
postValue 和 setValue
considerNotify 判断是否发送数据分析
粘性事件的分析
相信大家从以上几个角度去分析 LiveData 会有不小的收获💪
ViewModel
官方文档:https://developer.android.google.cn/topic/libraries/architecture/viewmodel
官方简介
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
生命周期
ViewModel 的生命周期会比创建它的 Activity、Fragment 的生命周期都要长。所以 ViewModel 中的数据会一直存活在 Activity/Fragment 中。
基础使用流程:
1.构造数据对象
自定义 ViewModel 类,继承 ViewModel,然后在自定义的 ViewModel 类中添加需要的数据对象
2.获取数据
有两种常见的 ViewModel 创建方式,第一种是在 activity 或 fragment 种直接基于 ViewModelProvider 获取。第二种是通过 ViewModelFactory 创建
使用 ViewModel 就是这么简单🚢
ViewModel 常见的使用场景
使用 ViewModel,在横竖屏切换后,Activity 重建,数据仍可以保存
同一个 Activity 下,Fragment 之间的数据共享
与 LiveData 配合实现代码的解耦
ViewModel 和 onSaveInstanceState 的区别
我相信大家一定知道 onSaveInstanceState,它也是用来保存 UI 状态的,你可以使用它保存你所想保存的东西,在 Activity 被杀死之前,它一般在 onStop 或者 onPause 之前触发。虽然 ViewModel 被设计为应用除了 onSaveInstanceState 的另一个选项,但是还是有一些明显的区别。由于资源限制,ViewModel 无法在进程关闭后继续存在,但 onSaveInstance 包含执行此任务。ViewModel 是存储数据的绝佳选择,而 onSaveInstanceState bundles 不是用于该目的的合适选项。
ViewModel 用于存储尽可能多的 UI 数据。因此,在配置更改期间不需要重新加载或重新生成该数据。
另一方面,如果该进程被框架关闭,onSaveInstanceState 应该存储回复 UI 状态所需的最少数据量。例如,可以将所有用户的数据存放在 ViewModel 中,而仅将用户的数据库 ID 存储在 onSaveInstanceState 中。
android onSaveInstanceState调用时机详细总结
ViewModel 和 Context
ViewModel 不应该包含对 Activity,Fragment 或 context 的引用,此外,ViewModel 不应包含对 UI 控制器(如 View)的引用,因为这将创建对 Context 的间接引用。当您旋转 Activity 被销毁的屏幕时,您有一个 ViewModel 包含对已销毁 Activity 的引用,这就是内存泄漏。因此,如果需要使用上下文,则必须使用应用程序上下文 (AndroidViewModel) 。
LiveData 和 ViewModel 的基本用法我们已经介绍完了,现在用几个例子带大家来更好的使用它们
案例一:计数器 — 两个 Activity 共享一个 ViewModel
话不多说,先上效果图:
虽然这个案例是比较简单的,但是我相信可以帮助你更快的熟悉 LiveData 和 ViewModel
想要实现效果图的话需要从下面几步来写(只讲解核心代码,具体代码请自己查看仓库):
第一步:创建 ViewModel
第二步:标记 ViewModel 的作用域
因为,我们是两个 Activity 共享一个 ViewModel,所以我们需要标记 ViewModel 的作用域
第三步:在 Activity 中使用(都是部分代码)
这样就可以实现效果图啦🏀
案例二:同一个 Activity 下的两个 Fragment 共享一个 ViewModel
话不多说,先上效果图
这个效果就很简单了,在同一个 Activity 下,有两个 Fragment,这两个 Fragment 共享一个 ViewModel
这个案例主要是想带大家了解一下 ViewModel 在 Fragment 中的使用
第一步:依旧是创建 ViewModel
非常简单的一个 ViewModel
第二步:在 Fragment 中使用
这样,这个简单的案例就实现啦。
尾述
终于把 LiveData 和 ViewModel 的大致使用讲解了一遍,但仅仅这样还是不够的,你还需要在更多更多的实践中去熟悉,去深入学习....
关于我
Hello,我是 Taxze,如果您觉得文章对您有价值,欢迎 ❤️,也欢迎关注我的博客。
如果您觉得文章还差了那么点东西,也请通过关注督促我写出更好的文章——万一哪天我进步了呢?😝
基础系列:
2022 · 让我带你Jetpack架构组件从入门到精通 — Lifecycle
学会使用 LiveData 和 ViewModel,我相信会让你在写业务时变得轻松🌞 (本文🌟)
以下部分还在码字,赶紧点个收藏吧🔥
2022 · 让我带你 Jetpack 架构组件从入门到精通 — DataBinding
2022 · 让我带你 Jetpack 架构组件从入门到精通 — Navigation
2022 · 让我带你 Jetpack 架构组件从入门到精通 — Room
2022 · 让我带你 Jetpack 架构组件从入门到精通 — Paging3
2022 · 让我带你 Jetpack 架构组件从入门到精通 — WorkManager
2022 · 让我带你 Jetpack 架构组件从入门到精通 — ViewPager2
2022 · 让我带你 Jetpack 架构组件从入门到精通 — 登录注册页面实战(MVVM)
进阶系列:
协程 + Retrofit 网络请求状态封装
Room 缓存封装
.....
版权声明: 本文为 InfoQ 作者【编程的平行世界】的原创文章。
原文链接:【http://xie.infoq.cn/article/81b241744143a59f8568bb30d】。
本文遵守【CC BY-NC】协议,转载请保留原文出处及本版权声明。
评论