C32476f5682da38173d38682a28edfe1
重学安卓:LiveData 鲜为人知的 身世背景 和 独特使命

前言

很高兴见到你!

上上上周,通过友人的介绍,我 承接并独立负责了 29 个页面、34 个 API、涉及 350 余个细节 的中大型电商软件的开发(感谢友人在项目后期 主动提出帮忙调整布局和对接 JS 😃)。

该软件有成熟的 iOS 实例,有专门适配 Android 的 360dp 设计稿,有 Restful API,所以尽管是第一次为合作方代工,总的来说还是一次满意的合作。

在该项目中,我广泛地采用了 Jetpack 架构组件。

事实上,正因为 依托于 Jetpack 面向标准化的、普适的 架构设计 和 理念规约,我才 得以在如此高强度的、紧凑的研发周期内,完成合作方原以为不太可能完成的任务

在有过这次研发经历后,我越发地想要向所有认识的、或者不认识的人推(qiang)荐(po)使用 Jetpack 架构组件。

并且,在架构组件中,如果说有哪个组件是我首推的,我一定会选择 LiveData。

被人云亦云者埋汰的 LiveData

在此之前,不少人对 LiveData 有着很深的误解,认为 LiveData 是个鸡肋的存在,并且老爱拿 RxJava 和 LiveData 比较。

如果你看到有谁在争论和抬杠:“RxJava 也能做到”,那他一定是在假装些什么。

事实上,RxJava 和 LiveData 的关系,就像物流中心的分拣员和配送员,是分工协作、完全不同的两个工种。

毫不客气地说,喜欢拿 RxJava 和 LiveData 比较的,不仅从未思考过 LiveData 存在的缘由,就连 RxJava,也不过是会一些表面招式,比那些完全没接触过 RxJava 的开发者好不到哪去。

更有甚者 —— 一个在评论区为争论而争论、所谓多年工作经验的 Android“大前端”,大言不惭地打算将 RxJava 直接用在视图控制器中、一步到位地完成数据请求响应的工作。

这已经不是有没有架构分层思想的问题了,这是连最基本的、关于视图控制器的基础知识 —— 生命周期、重建机制、状态管理 —— 都没掌握。

所以,今天这篇文章存在的缘由,就是为了帮助大家推开那些无聊的争论 和 嗡嗡作响的噪音,来 一睹真实的 LiveData,它究竟为超高效率、健壮而稳定的软件开发,带来了哪些不可思议的帮助 😉。

文章目录一览

  • 前言
  • 被人云亦云者埋汰的 LiveData
  • LiveData 的目标只有三个
  • LiveData 问世前的混沌世界
  • LiveData 为什么能解决这三个问题?
  • 综上

LiveData 的目标只有三个

这篇文章我反反复复地写了又推倒、推倒了又重写,因为立意特别困难 —— 我不能抛开 架构设计 和 理念规约 单独来介绍 LiveData —— 这样的 LiveData 是没有灵魂的。

LiveData 是在 架构设计面向标准化 的背景下诞生的,所以无论如何,我都要首先帮助读者了解状况:到底出于什么缘由,要存在 LiveData 这样的设计。

LiveData 的目标只有三个:

1.在 LifeCycler 的帮助下,实现生命周期管理的一致性,以及作用域的可控。

2.职责十分克制:仅限于让事件源注入状态、让订阅者观察状态,乃至于只能在单例的帮助下正常使用 —— 从而让新手老手 都能自然而然地遵循 从唯一可信源取材、完成状态的正确分发 —— 这样一种 得以将不可预期的错误降到最少 的状态管理理念。

3.就算不用 DataBinding,也能使 “单向依赖” 成为可能。

如果光是阅读了以上三点,你还是不太理解的话,那接下来我就分别介绍 99% 网文都不曾介绍的真实状况,来方便你迅速建立起感性的认识。😉

LiveData 问世前的混沌世界

例如这一次我开发的音频播放软件,其中最核心的功能是播放控制,它总共牵涉到 57 个业务细节。

这里我只拎出最具代表性的 3 个细节:

1.当音乐被暂停、播放时,所有涉及播放元素的界面 都要切换到对应的状态。

2.当切换歌曲时,所有涉及到当前歌曲信息的界面,都要正确展示信息。

3.当切换歌曲时,所有涉及专辑列表的界面,都要正确展示每一项的播放状态。

首页 专辑列表 播放页

(截图来自本次开发的电商软件《FairyTales》,Achieved by KunMinX with doubled patience and Love 😉)

第一条很好理解吧?如图所示,无论我是在首页、列表页、播放页、还是在通知栏触发了播放按钮,一旦播放状态被改变,那么所有包含展示播放状态的页面,都要及时同步状态。

第二条的意思是,切歌后,在播放页面等展示信息的地方,要正确展示当前专辑封面、歌曲的标题、作者等信息。

第三条细节,看似简单 —— 像前面 2 条一样,同步一下列表的 currentIndex (当前 item 的 index)就行?

实际上不是的,它背靠的是 “存在多种播放模式” 的背景,也即,当下可能处于 单曲循环、顺序播放、也可能处于 随机播放模式。

随机播放模式,实际使用的播放列表是一张打乱顺序的列表,是和给用户展示的专辑列表不同的列表。

那么如何处理 事件源 和 订阅者 的关系呢?

首先,既然要控制播放,自然是先封装一个播放控制的单例。

然后,为了解决状态同步的问题,可能首先想到的就是 EventBus —— 为每个页面都注册 EventBus,并且安排好监听方法。当任何一个页面发起通知,其他页面都跟着响应,做出对应的 UI 状态的变化。

看似就解决了 1、2 两个需求。

top Created with Sketch.