天天看點

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)
    }
}
           

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

LiveData的map()和switchMap官方文檔中的介紹例子差異總結相關文檔

結合代碼運作結果以及上面文檔中對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 ..
}
           

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

LiveData的map()和switchMap官方文檔中的介紹例子差異總結相關文檔

同樣的結合這個例子和上面的文檔描述,我們也可以得出一個結論: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就行。

相關文檔

  • Understanding LiveData made simple - Elye - Medium
  • What is the difference between map() and switchMap() methods? - stack overflow
  • LiveData 概覽 # 轉換 LiveData - Android Developer