LiveData的map()和switchMap

官方文檔中的介紹

在Android Developer官網上,對於map和switchMap的解釋是這樣的:

  • map:

Applies a function on the value stored in the LiveData object, and propagates the result downstream.

對存儲在 LiveData 對象中的值應用函數,並將結果傳播到下游。

  • switchMap:

applies a function to the value stored in the LiveData object and unwraps and dispatches the result downstream. The function passed to switchMap() must return a LiveData object, as illustrated by the following example:

對存儲在 LiveData 對象中的值應用函數,並將結果解封和分派到下游。傳遞給 switchMap() 的函數必須返回 LiveData 對象。

其實單純的看上面兩個官方文檔反而還會覺得更加的莫名其妙。其實這兩句話差異的核心在於 “解封”“返回LiveData對象”

例子

我們先來舉個栗子來說明下這兩個方法的區別(例子來源於此文章):

class TransformationMapFragment : Fragment() {

    private val changeObserver = Observer<String> { value ->
        value?.let { txt_fragment.text = it }
    }

    override fun onAttach(context: Context?) {
        super.onAttach(context)
        val transformedLiveData = Transformations.map(
                getLiveDataA()) { "A:$it" }
        transformedLiveData.observe(this, changeObserver)
    }
}

我們可以看到運行結果是這樣的:

在這裏插入圖片描述

結合代碼運行結果以及上面文檔中對map函數的定義,我們可以得出下面這個結論:map函數主要的功能就是根據原LiveData,對其原LiveData的值進行改變然後生成一個新的LiveData。基於原LiveData

而switchMap,同樣的,我們也來看一個例子:

class TransformationSwitchMapFragment : Fragment() {

    private val changeObserver = Observer<String> { value ->
        value?.let { txt_fragment.text = it }
    }

    override fun onAttach(context: Context?) {
        super.onAttach(context)

        val transformSwitchedLiveData =
            Transformations.switchMap(getLiveDataSwitch()) { 
                switchToB ->
                if (switchToB) {
                     getLiveDataB()
                } else {
                     getLiveDataA()
                }
        }

        transformSwitchedLiveData.observe(this, changeObserver)
    }
    // .. some other Fragment specific code ..
}

我們可以看到運行結果是這樣的:
在這裏插入圖片描述

同樣的結合這個例子和上面的文檔描述,我們也可以得出一個結論:switchMap是根據傳入的LiveData的值,然後判斷這個值,然後再去切換或者構建新的LiveData。手動生成新的LiveData

差異

所以對於這兩個函數的區別來說,map,更關注於數值的轉換,也就是說,他只會通過你之前的值去生成一個新的值,強調的是這個轉換,也就是說新的LiveData對象的值,仍然是基於當前這個LiveData的值而生成的。

而switchMap,更關注於數值的觸發,也就是說,他會監聽你這個值的變化,而不關注你這個值本身,你可以理解成觸發器或者扳機,當觸發之後,你就需要自己去主動的返回任意一個你指定的liveData對象。

所以我們再回過頭來看一下上面說的 “解封”“返回LiveData對象” :

對於這個,我覺得應該相對的來看,對於map來說,他把值從LiveData中讀取了出來,但是他只是在原值的基礎上進行操作生成新的LiveData對象,新的LiveData對象的值是基於舊的LiveData對象的,也就是說沒有完全的將值獨立出來;而對於switchMap,它不僅僅將值從LiveData中取出來了,並且取出來之後,對於新的LiveData來說,他並沒有要求新的LiveData的值必須得基於舊的LiveData咋樣,而是隻是單純的作爲一個觸發器,你返回的新的LiveData對象中存儲的值,與舊的LiveData對象的值有沒有關係,他並不在意。

總結

所以,總結一下。

map強調的是,新的LiveData的值必須基於舊的LiveData中的值(比方說像上面的例子,取出舊的LiveData的每個值然後加上相同的String從而生成新的LiveData)。

而switchMap,他並不在意這些,他在意的是他會將舊的LiveData的值作爲一個觸發,作爲一個switch,他不管你你到底是利用這個switch做判斷返回不用的值(像上面的例子),還是你利用這個值去網絡請求生成新的值(比方說舊的LiveData存了用戶名,而你根據這個用戶名去請求用戶的具體信息作爲新的LiveData返回)也好,只要你手動返回了一個新的LiveData就行。

相關文檔

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