本文是 《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
本質是 觀察者模式 的體現,可關鍵的問題是:網絡
討論這個問題以前,咱們先看看 LiveData
的用法,這實在沒什麼技術難度,好比,你能夠這樣實例化一個LiveData
並使用它:架構
如你所見,LiveData
實際上就像一個 容器, 本文中它存儲了一個String
類型的引用,每當這個容器內 String
的數據發生變化,咱們都能在回調函數中進行對應的處理,好比 Toast。app
這彷佛和咱們平常用到的 Button
控件的 setOnClickListener()
很是類似,實際上點擊事件的監聽也正是 觀察者模式 的一種體現,對於觀察者來講,它並不關心觀察對象 數據是如何過來的,而只關心數據過來後 進行怎樣的處理。框架
這也就是說,事件發射的上游 和 接收事件的下游 互不干涉,大幅下降了互相持有的依賴關係所帶來的強耦合性。函數
我依然堅持學習原理比學習如何應用的優先級更高,所以咱們先來一一探究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。
若是您以爲文章還差了那麼點東西,也請經過關注督促我寫出更好的文章——萬一哪天我進步了呢?