往期回顾,专栏目录,更新动态,优惠政策,版权须知
温馨提示:如这是第一次接触《重学安卓》,可通过上述链接快速了解《重学安卓》专栏,获取 专栏目录、试读内容、更新动态 和 发展状况。
截至目前,专栏已对 体系化文章 实施 3310 余次修订,数十位群友告诉我,受专栏启发 亦开启了写作之路。群里不定期会有小伙伴讨论适配问题、分享原创开源库 和 提供内推机会,订阅后可随时进群交流。
·
注:本文以《Jetpack MVVM 精讲》 以及《GitHub:Jetpack MVVM Best Practice》 作为前置知识,假设小伙伴已完整查阅并吸收上述内容。
前言
经过数年 实事求是 的互动交流,我们已共同演化完善《脚手架》开发模式 及《UnPeek-LiveData》、《Smooth-Navigation》、《Strict-DataBinding》等衍生开源库。
期间不时有小伙伴私信说,已在公司新项目中用上《脚手架》开发模式。
为何提及 “一致性问题”
谈到架构组件,不免提及 “一致性” 概念,该概念在相当长一段时间,都未在 Android 架构领域出现,
一切源于 2019 年发行《Jetpack MVVM 精讲》篇,加之 2021 年官方文档标语,该概念逐步传播和映入 Android 开发者视野。
其实就像 “内卷” 等词汇,“一致性” 并非新词,而是很早便存在于 “软件工程领域”,只是本人因缘巧合,对架构模式十分感兴趣,经由长期实践、反思、总结、跨界讨论,乃至有幸 为 “所观测现象” 匹配到 “精确概括”,
正式开始本文前,还须声明下,任何高度概括名词,皆是为方便指代某特定现象、为接下来真正要讨论的事情服务,故若非 “实事求是” 认识和解决问题 心态而来,请调整好心态再来,不然难踏实学习和有效交流。
文章目录一览
- 前言
- 为何提及 “一致性问题”
- 架构组件和 “一致性问题” 密切关系
- 到底什么是一致性、什么是一致性问题
- 关于 “解决一致性问题” 举一反三
- Lifecycle 是通过 实现 生命周期管理一致性
- LiveData 是通过 实现 消息同步一致性
- DataBinding 是通过 实现 View 实例 Null 安全一致性
- 综上
- Note 2022.07.12 加餐:
- 实战 1:设计一款 “领域层” 架构组件
- Note 2022.07.22 加餐:
- 实战 2:设计一款 Key-Value 组件
架构组件和 “一致性问题” 密切关系
首先此处 “架构” 特指 “业务架构”,也即在 “业务开发” 背景下,易存在各种 “不可预期” 错误(如 Crash 或 收到与预期不符数据),
这些 “不可预期” 错误,经由我们长期观测和交流发现,它们大都由所谓 “一致性问题” 引发,也即 解决一致性问题,即可最大程度规避 “不可预期” 错误,
故每当提及 “架构组件”,我们就会提及 “是为解决 xxx 一致性问题” —— “架构组件” 恰好即是为解决这类问题而生框架。
到底什么是一致性、什么是一致性问题
当我们谈论 “一致性” 时,通常是特指 “结果一致性”,例如 项目中存在多处雷同代码,当设计因需求发生改变时,我们务必在 修改 A 处同时,记得修改 B 处。而 “一致性问题” 即,我们 修改 A 处同时,忘修改 B 处。
这种因疏忽而导致的不可预期问题,十分普遍,造成疏忽原因也是千奇百怪(例如 A 处是同事 A 负责,B 处是同事 B 负责,同事 A 事先并不知道同事 B 也 copy 了一份同样代码,于是后续修改时就可能疏忽),
所以本着 “求之于势、不责于人” 态度,对于这类问题,我们不能苛责开发者务必做到 “不疏忽”,而是考虑 通过某种 “方式” 幕后默默将这些问题规避。
故简单来说,“一致性问题” 即 潜在的 “结果不一致”,或通俗话说即是 “改了 A 处,忘了 B 处”;而 “一致性目标” 即做到 “一处修改,处处生效、处处同步一致”。—— ©KunMinX
关于 “解决一致性问题” 举一反三
那上述 “某种方式” 究竟是什么?
经由广泛观察和提炼,本人发现 “内聚” 这词刚好能与之匹配。
下面我们便基于该认识、结合 Jetpack MVVM 架构组件来举一反三,之前阅读过 “架构组件系列文章” 小伙伴也可借此机会重温,看看自己对 “一致性” 及 “一致性问题” 理解,是否与原文本义相契。
Lifecycle 关注的是 “生命周期管理” 一致性
Lifecycle 解决的一致性问题主要体现在 “生命周期管理”。
以 LocationManager 为例,假设项目中 我们于多个 Activity 都有获取定位信息需求,传统办法是,在 LocationManager 中封装好 “激活、解除激活” 等方法,然后分别在 Activity onResume 和 onPause 节点调用这些方法,
后续 LocationManager 若有其他方法,我们不得不为这些 Activity 都改上一遍,而这便埋下一致性隐患,因为 项目规模变大、交接人员庞杂后,总有疏忽时。
旧时解决这类一致性问题办法是,写个 LocationActivity 基类,用到 LocationManager 的 Activity 都继承该基类,然而 Java 是单继承,这么做势必会使基类变得越来越大,最后不管有用没用东西都往里塞。
还记得《Activity 快乐你不懂》篇所述,通过 “组合模式” 对子类屏蔽不必要功能么?
—— 组合优于继承,故这种情况下,解决一致性问题 更好办法即是 “将生命周期管理工作 内聚到 LocationManager 组件中” —— 通过让 LocationManager 组件实现 DefaultLifecycleObserver 接口并在 Activity onCreate 时主动将自己添加到 Lifecycle 观察者队列中,这样一旦 Activity 生命周期节点发生变化,这些观察者组件也都能在自己内部收到通知和处理。
换言之,有注册就有被通知,没注册也没什么大不了,总之不会 “激活后又忘记解除激活” 等一致性问题而导致不可预期错误。