Fdb38663f15db47853349f8493b37a03
重学安卓:你是否还在用 EventBus 发消息?LiveData 唯一可信源 读写分离设计 独家解析

温馨提示:如果这是第一次接触《重学安卓》,可借助 这份在 GitBook 上维护的 “导读” 来快速了解《重学安卓》专栏、获取它的目录、试读内容,以及了解它的最新动态 和 发展状况。

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

·

注:本文以《Jetpack MVVM 精讲》《脚手架 - 架构模式解析》 以及

《GitHub:Jetpack MVVM Best Practice》 作为前置知识,

假设小伙伴已完整查阅并吸收了上述内容。

前言

你是否还在用 Bus 发消息?

最近网传 “比特币” 之类的数字加密货币暴跌,虽然我从不涉足 “炒币” 等领域,但我十分清楚,此类 “虚拟货币” 从交易安全的角度来说是 “极不可靠” 的,因为本质上它们属于 “去中心化” 的设计,

“去中心化” 意味着权限的分散,出了问题你很难追溯事情的源头,因而坏人们很容易利用这一点去操控市场行情,普通人入局就只有被割的份。

那么这件事和 EventBus 还有 LiveData 又有什么关系呢?如何才能确保交易 … 啊呸 … 消息分发的 “安全” 呢?

如果你也曾 加班加点地为 “不可预期的事件源” 的排查疲于奔命,相信存在某种设计能彻底规避这类事情的话,那么我们随时可以继续,今天我们就是专门通过 “通俗易懂” 的方式来解答这类问题 ~

文章目录一览

  • 前言
  • 绝对自由和自由的代价
  • 边界意识和监管下的真自由
  • LiveData 的本质和精髓
  • 所以 LiveDataBus 的本质是
  • 用工程化的语言再捋一捋
  • 关于 “唯一可信源” 的定义
  • 综上

绝对自由和自由的代价

EventBus 是 “消息收发自由” 框架的代表,通过它,使用者可以从任意角落发送消息,并让消息在任意目标角落接收到,只要 “发送者” 和 “观察者” 此刻都处于 “在线”(registed)的状态,

这是一种 “绝对的自由”,然而 “绝对的自由” 往往伴随着对潜在风险的全面忽视,例如

1.“观察者” 的代码块中包含 “可能已变为 null” 的成员变量,极容易引发 null 安全问题,

2.消息的可靠性没有保证,发送者发送的也许是过时的消息。

null 安全问题通常是以 App 崩溃来呈现,只需一次,就会给用户带来负面印象,而 Java 的 null 安全问题通常又难以在上线前发现,

所以有的团队改用 kotlin,在语法糖和 IDE 智能提示的协助下,主动发现潜在风险,和在编码过程中就将 null 安全问题规避,

那么关于 “不可预期事件推送” 的加班加点排查,主要就是上述提到的第二点,也即因为 “过时的”、“不一致” 的消息,而使 “单个页面内或多个页面之间,控件呈现的数据与预期不符”

—— 往往这时候你面临的是多个 “可能的发送源”,但你很难判断 “到底是哪个发送源分发的消息”,以及 “哪个发送源发送的消息才是可靠的”。

边界意识和监管下的真自由

通过长期的反思和践行,我们发现,这类问题的本质是 “公私不分” 和 “缺乏监管” —— 放任发送者误将私事当做公事 越界强加给边界外的他人,并在公事上缺乏统一的、具备公信力的机构来收紧决策权、在其内部统一决策、和统一对外公布。

首先我们先来明确一下,什么是 “私事”,什么是 “公事”,

私事就是个人边界内的东西,例如 私欲。

人际交往的层面 我们都知道要分清楚边界,不可随意越界将私欲丢给他人承担,页面交互的层面 其实同理:

把 App 看做一个部门,把 Fragments 看做是部门内的员工,那么 Fragment A 的成员变量,是它自己私域内的数据,它自己用无妨,但如果要去改变别的 Fragment(例如 Fragment B)的数据,它不能私自给 Fragment B 口头通知,不然就是犯规(因为不明就里的职场新人 Fragment B 收到了就会直接 “被迫营业”,万一结果出问题了,没有存证,找谁认责呢?),

那么怎么做才好呢?—— 明确边界,把握分寸 —— 作为员工,在部门内部的事情上,可以提议,但没有决策权,应把价值判断和做决定的权力还给领导,由领导来统一决策和通知,就算对领导的决策不满意,可以忍、可以离开,但无权越界干涉,

这样从大的格局来看,事情的运转就清晰了,因为私事只在私域内运转,私事要跨域,就得先上升为公事,而公事的决策结果究竟如何,由统一的监管小组来决策和通知,

因此,无论谁想 “发通知”,都不可随意发,而是改为 “向领导提议(request)”,由领导小组自行决策和统一通知,而这样也就最终确保了 “消息总是可靠的、一致的”,就算出问题,我不用找别人,我就找领导 —— 只需在 “领导” 这一处看看逻辑出了什么问题就行,

也即,要想彻底解决这类问题,就得明令禁止 EventBus 这类 “绝对自由” 框架的使用,转而寻求一种 “支持读写权限分离” 的消息通知框架,来支持 “唯一可信源消息分发” 的结构设计

LiveData 应运而生。

LiveData 的本质和精髓

上述我们提到了 “发消息” 面临的两大潜在风险,基于这个背景,我们轻易得以推知 LiveData 的本质 ——

1.不是每个团队、每个项目都用 kotlin,所以 LiveData 有必要承担一部分 null 安全问题的规避,所以 LiveData 借助 Lifecycle 框架来在 “绝对安全” 的几个生命周期节点对 消息通知保持开放,以确保 View 实例调用 不因生命周期而发生 null 安全问题

注意它只是防生命周期的情况,其他因素导致的 视图实例为 null 的情况,它防不住,所以它的防护效果其实有限,要彻底防住还是需要 《DataBinding 严格模式》 或改用 kotlin。

2.提供 “读写分离” 的设计。注意 LiveData 被设计为父类,setValue 和 postValue 都是 protected 权限,而 public 权限只存在于 MutableLiveData 中,

由于英文不是中国人的母语,因而多数开发者没有去理解,甚至都没有去查一查 Mutable 的意思,很简单,其实就是 “可变” 的意思,

top Created with Sketch.