Android Jetpack架構組件-LiveData使用

谷歌推出的LiveData和RxJava類似,也是基於觀察者,你可以認爲LiveData是輕量級的RxJava。起初LiveData並不被看好,隨着谷歌的大力推廣,LiveData也慢慢的進入了大家的視野。一般來說,LiveData很少單獨使用,它更多的和Android
Jetpack的其他組件搭配使用,比如和ViewModel、Room、Paging等。這篇文章就來介紹LiveData的使用。

一、定義

LiveData 是一種可觀察的數據存儲器類。與常規的可觀察類不同,LiveData 具有生命週期感知能力,意指它遵循其他應用組件(如 Activity、Fragment 或 Service)的生命週期。這種感知能力可確保 LiveData 僅更新處於活躍生命週期狀態的應用組件觀察者。

二、優勢:

使用 LiveData 具有以下優勢:

  • 確保界面符合數據狀態

    LiveData 遵循觀察者模式。當生命週期狀態發生變化時,LiveData 會通知 Observer 對象。您可以整合代碼以在這些 Observer 對象中更新界面。觀察者可以在每次發生更改時更新界面,而不是在每次應用數據發生更改時更新界面。

  • 不會發生內存泄露

    觀察者會綁定到 Lifecycle 對象,並在其關聯的生命週期遭到銷燬後進行自我清理。

  • 不會因 Activity 停止而導致崩潰

    如果觀察者的生命週期處於非活躍狀態(如返回棧中的 Activity),則它不會接收任何 LiveData 事件。

  • 不再需要手動處理生命週期

    界面組件只是觀察相關數據,不會停止或恢復觀察。LiveData 將自動管理所有這些操作,因爲它在觀察時可以感知相關的生命週期狀態變化。

  • 數據始終保持最新狀態

    如果生命週期變爲非活躍狀態,它會在再次變爲活躍狀態時接收最新的數據。例如,曾經在後臺的 Activity 會在返回前臺後立即接收最新的數據。

  • 適當的配置更改

    如果由於配置更改(如設備旋轉)而重新創建了 Activity 或 Fragment,它會立即接收最新的可用數據。

  • 共享資源

    您可以使用單一實例模式擴展 LiveData 對象以封裝系統服務,以便在應用中共享它們。LiveData 對象連接到系統服務一次,然後需要相應資源的任何觀察者只需觀察 LiveData 對象,後文都會提高

三、使用liveData

LiveData的數據源一般是ViewModel,也可以是其它可以更新LiveData的組件。當數據更新後,LiveData 就會通知它的所有觀察者,比如Activiy。

與RxJava的方法不同的是,LiveData並不是通知所有觀察者,它只會通知處於Active狀態的觀察者,如果一個觀察者處於Paused或Destroyed狀態,它將不會收到通知。

這對於Activiy和Service特別有用,因爲它們可以安全地觀察LiveData對象而不用擔心內存泄漏的問題。開發者也不需要在onPause或onDestroy方法中解除對LiveData的訂閱。還有一點需要注意的是一旦觀察者重新恢復Resumed狀態,它將會重新收到LiveData的最新數據。

3.1、 LiveData的基本使用

示例爲Button事件點擊,LiveData發送個數據,觀察者接收到數據更新以後更新UI

class LiveDataActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data)

        var liveData: LiveData<String> = MutableLiveData<String>()

        btn_ald_post.setOnClickListener {
             //發送數據
            (liveData as MutableLiveData).postValue("有新消息了")
        }

      	//觀察livedata對象
        liveData.observe(this, Observer<String> {
          	//Updata UI
            tv_ald_info.text = it
        })
    }
}

liveData.observe(this,Observer)方法有兩個參數分別是LifecycleOwnerObserver ,第一個參數就是LiveDataActivity本身,因爲父類已實現了LifecycleOwner接口,詳情可參考筆者Lifecycle的文章,第二個參數則新建了一個Observer,在onChanged方法中得到回調。註釋處的postValue方法會在主線程中更新數據,這樣就會更改TextView中text屬性的值。

在大多數情況下,LiveData的observe方法會放在onCreate方法中,如果放在onResume方法中,會出現多次調用的問題。除了MutableLiveData的postValue方法,還可以使用setValue方法,它們之前的區別是,setValue方法必須在主線程使用,如果是在工作線程中更新LiveData,則可以使用postValue方法。

3.2、 更改LiveData中的數據

如果我們想要在LiveData對象分發給觀察者之前對其中存儲的值進行更改,可以使用Transformations.map()Transformations.switchMap(),類似於Rxjava中的map()方法
下面通過簡單的例子來講解它們

        var liveData: LiveData<String> = MutableLiveData<String>()

        btn_ald_post.setOnClickListener {
            (liveData as MutableLiveData).postValue("有新消息了")
        }

        var changLiveData = Transformations.map(liveData) {
            it + "changed"
        }

        changLiveData.observe(this, Observer<String> {
            tv_ald_info.text = it
        })

運行結果爲TextView的值爲

"有新消息changed"

3.3、 Transformations.switchMap()

如果想要手動控制監聽其中一個的數據變化,並能根據需要隨時切換監聽,這時可以使用Transformations.switchMap(),它和Transformations.map()使用方式類似,只不過switchMap()必須返回一個LiveData對象。

MediatorLiveDataLiveData 的子類,允許您合併多個 LiveData 源。只要任何原始的 LiveData 源對象發生更改,就會觸發 MediatorLiveData 對象的觀察者。

例如,如果界面中有可以從本地數據庫或網絡更新的 LiveData 對象,則可以向 MediatorLiveData 對象添加以下源:

  • 與存儲在數據庫中的數據關聯的 LiveData 對象。
  • 與從網絡訪問的數據關聯的 LiveData 對象。

    代碼如下所示:
class MergerLiveDataActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_merger)
        
        val mutableLiveData1 = MutableLiveData<String>()
        val mutableLiveData2 = MutableLiveData<String>()
        val mutableLiveData3 = MutableLiveData<String>()
        val liveDataMerger: MediatorLiveData<*> = MediatorLiveData<String>()
        
        liveDataMerger.addSource(mutableLiveData1, object : Observer<String> {
            override fun onChanged(t: String?) {
                Log.d("TAG", "onChanged1:$t")
            }
        })

        liveDataMerger.addSource(mutableLiveData2, object : Observer<String> {
            override fun onChanged(t: String?) {
                Log.d("TAG", "onChanged2:$t")
            }
        })
        
        liveDataMerger.addSource(mutableLiveData3, object : Observer<String> {
            override fun onChanged(t: String?) {
                Log.d("TAG", "onChanged3:$t")
            }
        })
        
        liveDataMerger.observe(this, Observer {
            Log.d("TAG", "onChanged:$it");
        })
        

        mutableLiveData1.postValue("Onexzgj 的Jetpack")
        mutableLiveData2.postValue("Onexzgj 的Jetpack2")
        mutableLiveData3.postValue("Onexzgj 的Jetpack3")
    }
}

爲了更直觀的舉例,將LiveData和MediatorLiveData放到了同一個Activity中。通過MediatorLiveData的addSource將兩個MutableLiveData合併到一起,這樣當任何一個MutableLiveData數據發生變化時,MediatorLiveData都可以感知到。

打印結果如下,任何一個liveData發生變化,liveDataMerger都會接受到通知
在這裏插入圖片描述

3.4、擴展LiveData對象

如果觀察者的生命週期出於STARTED或者RESUMED狀態,LiveData會將觀察者視爲處於Active狀態,關於如何擴展LiveData,官網的例子比較簡潔,如下所示:

    class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
        private val stockManager = StockManager(symbol)

        private val listener = { price: BigDecimal ->
            value = price
        }

        override fun onActive() {
            stockManager.requestPriceUpdates(listener)
        }

        override fun onInactive() {
            stockManager.removeUpdates(listener)
        }
    }

上面的代碼是一個觀察股票變動的一個例子,對LiveData進行了拓展,實現了LiveData的兩個空方法onActive和onInactive。當Active狀態的觀察者的數量從0變爲1時會調用onActive方法,通俗來講,就是當LiveData對象具有Active狀態的觀察者時調用onActive方法,應該在onActive方法中開始觀察股票價格的更新。當LiveData對象沒有任何Active狀態的觀察者時調用onInactive方法,在這個方法中,斷開與StockManager服務的連接。

LiveData 對象具有生命週期感知能力,這一事實意味着您可以在多個 Activity、Fragment 和 Service 之間共享它們。爲使示例保持簡單,所以可以將 LiveData 類實現爲單一實例,如下所示:

 class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
        private val stockManager: StockManager = StockManager(symbol)

        private val listener = { price: BigDecimal ->
            value = price
        }

        override fun onActive() {
            stockManager.requestPriceUpdates(listener)
        }

        override fun onInactive() {
            stockManager.removeUpdates(listener)
        }

        companion object {
            private lateinit var sInstance: StockLiveData

            @MainThread
            fun get(symbol: String): StockLiveData {
                sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
                return sInstance
            }
        }
    }

因此在Fragment中使用如下所示:

    class MyFragment : Fragment() {
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            StockLiveData.get(symbol).observe(this, Observer<BigDecimal> { price: BigDecimal? ->
                // Update the UI.
            })
        }

多個 Fragment 和 Activity 可以觀察 MyPriceListener 實例。僅當一個或多個系統服務可見且處於活躍狀態時,LiveData 纔會連接到該服務。

四、總結

這篇文章主要介紹了什麼是LiveData,以及LiveData的使用方法,這裏沒有介紹LiveDataViewModel的結合使用,以及LiveData的原理,這些會在後面的文章進行介紹。

最後文章中涉及到的源碼及Jetpack的全組件均上傳至OnexZgj/Jetpack_Component

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章