本文是 《Android Jetpack 官方架构组件》 系列文章, LiveData
自己很简单,但其表明却正是 MVVM 模式最重要的思想,即 数据驱动视图(也有叫观察者模式、响应式等)——这也是摆脱 顺序性编程思惟 的重要一步。android
咱们都知道Google在去年的 I/O 大会很是隆重地推出了一系列的 架构组件,本文的主角,LiveData 正是其中之一,和Lifecycle
、ViewModel
、Room
比较起来,LiveData
能够说是最受关注的组件也不为过,遗憾的是,在发布的最初,关注点是由于它饱含争议,至关一部分的开发者认为——LiveData
实在太 鸡肋 了!git
2017年的 Android
技术领域,RxJava
无疑是煊赫一时的名词之一,其 观察者模式 和 链式调用 所表现出来的 API 优秀地设计,使得它位于不少 Android项目技术选型中的 第一序列。github
这时 Google 隆重推出了具备相似功能的 LiveData
(其本质就是观察者模式),能够说是有点初生牛犊不怕虎的感受,开发者们情不自禁将LiveData
和 RxJava
进行了对比,结论基本出奇的一致—— LiveData
所提供的功能,RxJava
彻底足以胜任,然后者却同时具备庞大的生态圈,这是LiveData
短期内难以撼动(替代)的。面试
时至今日,LiveData
的使用者愈来愈多,最主要的缘由固然和Google的强力支持不无关系,可是LiveData
自己优秀的设计和轻量级也吸引了愈来愈多开发者的青睐。编程
如今咱们须要去了解它了,咱们都知道,LiveData
本质是 观察者模式 的体现,可关键的问题是:markdown
讨论这个问题以前,咱们先看看 LiveData
的用法,这实在没什么技术难度,好比,你能够这样实例化一个LiveData
并使用它:网络
如你所见,LiveData
实际上就像一个 容器, 本文中它存储了一个String
类型的引用,每当这个容器内 String
的数据发生变化,咱们都能在回调函数中进行对应的处理,好比 Toast。架构
这彷佛和咱们平常用到的 Button
控件的 setOnClickListener()
很是类似,实际上点击事件的监听也正是 观察者模式 的一种体现,对于观察者来讲,它并不关心观察对象 数据是如何过来的,而只关心数据过来后 进行怎样的处理。app
这也就是说,事件发射的上游 和 接收事件的下游 互不干涉,大幅下降了互相持有的依赖关系所带来的强耦合性。框架
我依然坚持学习原理比学习如何应用的优先级更高,所以咱们先来一一探究LiveData
自己设计中存在的那些闪光点背后的故事。
咱们都知道,RxJava
在使用过程当中,避免内存泄漏是一个不可忽视的问题,所以咱们通常须要借助三方库好比RxLifecycle
、AutoDispose
来解决这个问题。
而反观LiveData
,当它被咱们的Activity
订阅观察,这以后Activity
若是finish()
掉,LiveData
自己会自动“清理”以免内存泄漏。
这是一个很是好用的特性,它的实现原理很是简单,其本质就是利用了Jetpack 架构组件中的另一个成员—— Lifecycle。
让咱们来看看LiveData
被订阅时内部的代码:
源码中的逻辑很是复杂,咱们只关注核心代码:
LiveData.observer()
方法时,传递的第一个参数Acitivity
实际被向上抽象成为了 LifecycleOwner
,第二个参数Obserser
实际就是咱们的观察后的回调。这里咱们须要注意的是,执行
LiveData.observer()
方法时 必须处于主线程,不然会由于断言失败而抛出异常。
LifecycleBoundObserver
对象,它实现了 Lifecycle 组件中的LifecycleObserver
接口:这里就解释了为何LiveData
可以 自动解除订阅而避免内存泄漏 了,由于它内部可以感应到Activity
或者Fragment
的生命周期。
这种设计很是巧妙——在咱们初识 Lifecycle 组件时,老是下意识认为它可以对大的对象进行有效生命周期的管理(好比 Presenter),实际上,这种生命周期的管理咱们彻底能够应用到各个功能的基础组件中,好比大到吃内存的 MediaPlayer(多媒体播放器)、绘制设计复杂的 自定义View,小到随处可见的LiveData
,均可以经过实现LifecycleObserver
接口达到 感应生命周期并内部释放重的资源 的目的。
关于上述代码中注释了 更新LiveData的活跃状态 的源码,咱们先跳过,稍后咱们会详细探讨它。
LiveData
来说,固然存在多个观察者同时订阅观察的状况,所以考虑到这一点,Google的工程师们为每个LiveData
配置了一个Map
存储全部的观察者。4.到了这一步,咱们将第2步包装生成的对象交给咱们传入的 Activity
,让它在不一样的生命周期事件中去逐一通知其全部的观察者,固然也包含了咱们的LiveData
。
LiveData
原生的API提供了2种方式供开发者更新数据, 分别是 setValue()
和postValue()
,官方文档明确标明:setValue()
方法必须在 主线程 进行调用,而postValue()
方法更适合在执行较重工做 子线程 中进行调用(好比网络请求等)——在全部状况下,调用setValue()
或postValue()
都会 触发观察者并更新UI。
柿子挑软的捏,咱们先看setValue()
方法的实现原理:
经过保留最终的核心代码,咱们很清晰了解了setValue()
方法为何能更新LiveData
的值,而且通知到回调函数中的代码去执行,好比更新UI。
可是咱们知道,广泛状况下,Android不容许在子线程更新UI,可是postValue()
方法却能够在子线程更新LiveData()
的数据,并通知更新UI,这是如何实现的呢?
其实答案已经呼之欲出了,就是经过 Handler
:
如今你已经对LiveData
总体了一个基本的了解了,接下来让咱们开始去探究更细节的闪光点。
LiveData
自己很是简单,毕竟它自己的源码一共也就500行左右,也许你要说 准备面试粗读一遍源码就够了,很遗憾,即便是粗读了源码,也很难说可以彻底招架更深刻的提问...
让咱们来看一道题目:在下述Activity完整的生命周期中,Activity
一共观察到了几回数据的变动——即 一共打印了几条Log ?(补充纠正,onStop()方法中值应该为 "onStop")
公布答案:
意外的是,livedata.observer()
的本次观察并无观察到 onCreate、onStop 和 onDestroy 的数据变动。
还记得上文提到过2次的 LiveData的活跃状态(Active) 相关代码吗?实际上,LiveData
内部存储的每个LifecycleBoundObserver
自己都有shouldBeActive
的状态:
如今咱们明白了,原来并非只要在onDestroy()
以前为LiveData
进行更新操做,LiveData
的观察者就能响应到对应的事件的。
虽然咱们明白了这一点,可是若是更深刻的思考,你会又多一个问题,那就是:
LiveData
已经可以实如今onDestroy()
的生命周期时自动解除订阅,为何还要画蛇添足设置一个Active
的状态呢?仔细想一想,其实也不可贵到答案,Activity
并不是只有onDestroy()
一种状态的,更多时候,新的Activity
运行在栈顶,旧的Activity
就会运行在 background
——这时旧的Activity
会执行对应的onPause()
和onStop()
方法,咱们固然不会关心运行在后台的Activity
所观察的LiveData
对象(即便数据更新了,咱们也无从进行对应UI的更新操做),所以LiveData
进入 **InActive(待定、非活跃)**状态,return
而且不去执行对应的回调方法,是 很是缜密的优秀设计 。
固然,有同窗提出,我若是但愿这种状况下,Activity
在后台依然可以响应数据的变动,可不能够呢?固然能够,LiveData
此外还提供了observerForever()
方法,在这种状况下,它可以响应到任何生命周期中数据的变动事件:
除此以外,源码中到处都是优秀的细节,好比对于observe()
方法和observerForever()
方法对应生成的包装类,后者方法生成的是AlwaysActiveObserver
对象,统一抽象为ObserverWrapper
。
这种即便只有2种不一样场景,也经过代码的设计,将公共业务进行向上抽离为抽象类的严谨,也很是值得咱们学习。
原本写了更多,篇幅所限,最终仍是决定删除了至关一部分和 RxJava
有关的内容,这些内容并不是是将 LiveData
和 RxJava
进行对比一决高下—— 例如,Google官方提供了 LiveData
和 RxJava
互相进行转换的工具类:
developer.android.com/reference/a…
值得玩味的是,官方的工具类中,LiveData
向RxJava
的转换方法,返回值并不是是一个Flowable
,而是一个Publisher
接口:
正如我在注释中标注的,这个工具方法返回的是一个接口,很大程度上限制了咱们对RxJava
众多强大操做符的使用,这是不是来自Google的恶意?
固然不是,对于这种行为,个人理解是Google对于LiveData
自己严格的约束——它只应该用于进行数据的观察,而不是花哨的操做;转换为Flowable固然很是简单,可是这种行为是否属于LiveData
自己职责的逾越,更准确来讲,是否属于没必要要的过分设计?这些是咱们须要去细细揣度的。
我无从验证个人理解是否正确,可是个人这个理由已经足够说服我本身,再往下已再也不是LiveData
的范畴,关于这一点我将会专门起一篇文章去进行更深刻的探讨,欢迎关注。
--------------------------广告分割线------------------------------
争取打造 Android Jetpack 讲解的最好的博客系列:
Android Jetpack 实战篇:
Hello,我是却把清梅嗅,若是您以为文章对您有价值,欢迎 ❤️,也欢迎关注个人我的博客或者Github。
若是您以为文章还差了那么点东西,也请经过关注督促我写出更好的文章——万一哪天我进步了呢?