A194acbebe4a15173fc24f62ae7bea13
重学安卓:吃透 LiveData 本质,享用可靠的消息鉴权机制

往期回顾专栏目录更新动态优惠政策版权须知

温馨提示:如果这是第一次接触《重学安卓》,可通过上述链接来访问和快速了解《重学安卓》专栏、获取它的目录、试读内容,以及了解它的最新动态 和 发展状况。

截至目前,专栏已对 体系化文章 做了 1970 余次修订,数十位群友告诉我 受专栏的启发 他们也开启了写作之路。群里不定期会有小伙伴讨论适配问题、分享原创的开源库 和 提供内推机会,订阅后可随时进群交流。

·

重要提示

阅读本文的最佳时机是,您已吃过 阅读 “源码” 或 “源码分析文” 时 找不到头绪的苦

您还没吃过苦,那您先不要着急阅读本文。您得吃过苦,才会有体会。

在您吃够这方面的苦后,您才有机会发现,本文正是专用于解决 “如何找到正确打开方式” 的困扰。

我们绝不通篇贴源码,而是基于广泛的实践和反思,在累积过大量样本 乃至足以排除掉所有干扰信息后,点到为止地揭露 LiveData 框架最为核心的本质,方便您理解其真实的存在意义,乃至可以笃信地将其用在项目中。

关于 LiveData 在项目中的实践,请另行查阅《GitHub : Jetpack-MVVM-Best-Practice》源码,以及《架构模式实践》篇 的完整解析。

前言

经过 2 年的修订和交流,关于 LiveData 的各角度理解已尘埃落定,所以这一期,我们以简练的话语,循序渐进将 “LiveData 的本质” 铺陈开来。

如果你已爬过阅读源码的坑,并且是第一次阅读本专栏关于 LiveData 的内容,那么通过本文可以了解到,关于 LiveData,最多可以了解到什么程度。

如果过去 2 年你已反复通读本专栏 “架构模式” 乃至 LiveData 相关的内容,那么本文可以作为参考,检验自己对 LiveData 的理解 是否和我们所介绍的一致。

文章目录一览

  • 前言
  • 第一层:LiveData 是与 UI 打交道的 “最后一环”
  • 第二层:LiveData 可以推状态,也可以推事件
    • 广播:封闭式 的 发布订阅模式
  • 第三层:LiveData 支持 “唯一可信源” 的鉴权设计
    • 状态是私域的,事件是公域的
    • 公证处:开放式 的 发布订阅模式
  • 第四层:LiveData 存在 “数据倒灌” 的问题
    • 使用 UnPeek-LiveData 解决 “数据倒灌” 问题
  • 综上

第一层:LiveData 是与 UI 打交道的 “最后一环”

LiveData 内部是 “观察者模式” 的设计,通过 Map 来维护观察者序列,上游通过 setValue 来推送最新消息,下游的观察者们便能收到消息,在 Activity/Fragment 等 “视图控制器” 中处理剩余的 UI 逻辑。

但如果仅此而已,还用 LiveData 干啥呢?EventBus 不香吗?或者直接写个 interface 回调不就完了么?

所以为什么要使用 LiveData,为什么考虑将其作为 “最后一环” …

因为 LiveData 可缓存值,且包含 “生命周期安全” 的设计

LiveData 没观察者时不发送 且保留值,有观察者注册时就发送,并且由于 LiveData 内部有 Lifecycle 组件的加持,使得进一步约束为 “观察者活跃时才发送,观察者不活跃时不发送”,

—— 如此减少了不必要的性能浪费,且确保了 “生命周期安全”,避免在 onStop 等不稳定的环节被推送消息、被迫执行回调逻辑而发生 crash 等现象(因为 onStop 有可能是 “回到桌面” 或 “切换 App” 引发的,而这两者在 “非原生系统” 中又是可能存在不可预期的问题)

第二层:LiveData 可以推状态,也可以推事件

基于第一层的认识,人们明白 LiveData 相比 EventBus 或 interface 的好处是,有 Lifecycle 的加持乃至能够规避 “不必要的性能浪费” 和确保 “生命周期安全”,尽可能避免由此引发的 null 安全等问题。

因而基于这一层理解,有人试图基于 “发布订阅模式”,将 LiveData 封装为 LiveDataBus,这样就可以通过 LiveDataBus 在页面之间发送生命周期安全的事件了。

所谓 “发布订阅模式”,就是在普通 “观察者模式” 中引入 “中间人/代理人”,发送者的消息不是直接推送到观察者,而是经由 “中间人/代理人” 来推送,这样做的好处是,中间人可以 实施鉴权、可以 筛选消息 并推送给指定分组的观察者,而不像 “观察者模式” 那样 观察者们无差别地承受所有推送

广播:封闭式 的 发布订阅模式

但这里值得注意的是,无论 LiveDataBus 还是 EventBus,它们本质上都是 “广播” —— 一种 “封闭式” 的 “发布订阅模式”,

也即它们的 “中间人/代理人” 逻辑是封闭的、写死的,仅仅起到代码 “解耦” 的作用 —— 解耦了 “观察者” 和 “发送者” 页面,因此还有个事实上更为重要的问题没有解决。

第三层:LiveData 支持 “唯一可信源” 的鉴权设计

最开始接触 LiveData 和 MutableLiveData 的时候,多数人估计一脸懵逼 —— 为什么要将 LiveData 的 setValue 和 postValue 设置为 protected,然后在 MutableLiveData 中设置为 public —— 就是官方文档也没有说出个所以然。

然而在长足的爬坑过程中,你若经历过多次 为 “消息推送难以溯源”、“消息同步不可靠不一致” 等问题加班排查到半夜十二点,便有机会追溯造成此类现象的最根本因素,顿悟 “状态”、“事件” 的区别,乃至萌生 “唯一可信源” 的鉴权设计理念。

top Created with Sketch.