Android Jetpack 應用指南(一) - LiveData

前言

從事Android開發兩年有余了,從15年開始學習Android,到17年開始實際接觸企業級Android APP的開發,這一路也從MVC走到了MVP。19年辭職后,休息期間研究了一下最新的Android Jetpack,萌生了一個大膽的想法——計劃使用當前各類成熟的框架和技術如組件化、插件化、MVVM等等,結合AAC開發出一個自己之前從未走過的Android開發之路。

本篇文章是LiveData的初探,會用盡可能簡潔的方式來了解LiveData,讓我們對LiveData有一個初步印象,不會長篇大論或者源碼轟炸,導致干貨太多引起閱讀困難。

目錄

  • LiveData生命周期與簡介
  • LiveData的使用
  • LiveDataAPI介紹
  • LiveData的擴展
  • LiveData數據轉換

正文

LiveData簡介

LiveData的官方文檔是這樣介紹它的,
LiveData是一種具有生命周期感知能力的可觀察數據持有類。
從它介紹中我們可以知道,LiveData是一個持有數據的類,同時可以感知Activity或Fragment的生命周期,并且支持觀察者模式。

LiveData的使用

根據官方的介紹,可以按照以下的步驟來使用LiveData

1.創建一個LiveData的實例來保存特定類型的數據。 一般會把LiveData的實例定義在ViewModel類中。

    val name: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

MutableLiveData是LiveData的一個子類,LiveData是一個抽象類,實例化LiveData需要使用MutableLiveData。

2.創建一個定義了onChanged()方法的Observer對象,當LiveData對象保存的數據發生變化時,onChanged()方法可以進行相應的處理。

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

        //創建viewmodel
        mViewModel = ViewModelProviders.of(this).get(LiveDataViewModel::class.java)

        //聲明觀察TextView對象,
        mViewModel.name.observe(this, Observer {
            //實現onChanged()方法,這里使用了lambda表達式,省略了onChanaged()
            textview.text = it
        })

    }

通常在UI控制器(如Activity或Fragment)中創建Observer對象。

3.調用LiveData的observe()方法需要傳入兩個參數,第一個參數LifecycleOwner對象,LifecycleOwner是一個接口,只要UI控制器實現了該接口,可以直接傳this,Android中的Fragment和AppCompatActivity的父類都已經實現LifecycleOwner接口。第二個參數是Observer觀察者,屬于方法回調。

更新LiveData數據

MutableLiveData提供了兩個更新數據的方法

  • postValue(value: T)
  • setValue(value: T)

兩個方法都可以用來更新LiveData中數據,區別在與postValue可以在子線程中更新LiveData的數據,而setValue只能在UI線程中更新LiveData的數據。

注意: UI控制器(activity和fragment)只應該負責顯示數據,不應該保存任何數據,所以不要在UI控制器中創建LiveData的實例。

LiveDataAPI介紹

getValue():T

返回LiveData當前的存儲的值

hasActiveObservers():Boolean

如果當前的LiveData存在活躍的Observer對象,則返回true

hasObservers():Boolean

如果當前的LiveData存在Observer對象,則返回true

observe(@NonNull owner: LifecycleOwner, @NonNull observer: Observer<in T>)

將給定的觀察者添加到給定所有者的生命周期內的觀察者列表中。

observeForever(@NonNull observer: Observer<in T>)

注冊一個沒有關聯LifecycleOwner對象的Observer。 在這種情況下,Observer被認為始終處于活動狀態,因此當有數據變化時總是會被通知。 可以調用removeObserver(Observer)方法移除這些Observer。

removeObserver(@NonNull observer: Observer<in T>)

從觀察者列表中刪除給定的觀察者。

removeObservers(@NonNull owner: LifecycleOwner)

刪除與給定關聯的所有觀察者LifecycleOwner。

LiveData的擴展

LiveData的擴展千變萬化,這里只介紹LiveData的源碼中預留的兩個空實現方法的擴展

  • onActive()

當LiveData對象有一個活躍的Observer時,onActive()方法被調用。

  • onInactive()

當LiveData對象沒有任何活躍的Observer時,onInactive()方法被調用。

通過onActive和onInactive方法我們可以很輕松的知道當前LiveData對象是否有正在活躍的觀察者對象,并根據業務邏輯作出合適的調整。

LiveData對象具有感知生命周期的能力意味著可以在多個Activity,Fragment和service之間共享它們。 為了保持簡潔,可以使用單例模式實現LiveData

class ExpandLiveData :LiveData<String>() {


    companion object {
      private lateinit var sInstance: ExpandLiveData

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

    //當活動的觀察者數量從0變為1時調用。
    override fun onActive() {
        super.onActive()
    }

    //當活動的觀察者數量從1變為0時調用。
    override fun onInactive() {
        super.onInactive()
    }


}

在activity中就可以用如下的方式調用

    ExpandLiveData.get().observe(this, Observer {
        //doSomething
    })

LiveData的數據轉換

通過上述的介紹,我們對LiveData有了一個初步的印象,LiveData是一個可以感知生命周期的的數據持有類,同時支持觀察者模式。說到觀察者模式,我們一定會聯想到Rxjava,Rxjava中提供了多種多樣的操作符,極大的便利了Android開發。LiveData的開發者們同樣也給LiveData帶來了與Rxjava類似的多種操作符。
與Rxjava不同的是,在LiveData中需要借助Transformations類來完成LiveData的數據轉換

  • map(liveData,function)

map操作符,與rxjava的map操作符語義非常相似,可修改LiveData的輸出值。map方法有兩個參數,第一個參數是需要轉換的LiveData源,第二個參數是自定義的轉換方法。示例如下:

    val newLiveData = Transformations.map(ExpandLiveData.get()) { string ->
        //把轉換前的livedata的value加了一個new
        "new$string"
    }

    newLiveData.observe(this, Observer { string ->
        Log.e("newLiveData", string)
    })

    ExpandLiveData.get().observe(this, Observer { string ->
        Log.e("ExpandLiveData", string);
    })

輸出結果:

E/newLiveData: newExpand
E/ExpandLiveData: Expand
  • switchMap

switchMap與map相似,區別在于:map給出的是具體的值,而switchMap給出的是具體的LiveData。

舉個例子:有這樣一個方法getUser(Id),通過傳入用戶的Id,來查找用戶的具體信息,并返回一個LiveData<User>對象。當界面傳入的用戶Id發生變化時,需要根據Id重新查找用戶的LiveData,這時就需要解除上一個LiveData關聯界面UI信息,綁定新的UI消息。如果我們使用switchMap,就可以避免重復的解綁和綁定操作。示例如下:

    //模擬查找用戶的操作,這里重新生成了一個UserLiveData
    fun getUser(id: String): MutableLiveData<String> {
        //返回查到的UserLiveData,value是固定link加上用戶的Id,例如:userId=1000,返回值就是link-1000
        val userLiveData=MutableLiveData<String>()
        userLiveData.value="link-${id}"
        return userLiveData
    }
    
    //用一個按鈕來模擬修改UserId
    button.setOnClickListener {
        //通過隨機數動態修改userId
        userIdLiveData.value = Random.nextInt(0, 10000).toString()
    }
    
    //通過switchMap動態返回不同Id的UserLiveData
    val userIdLiveData = MutableLiveData<String>()
    Transformations.switchMap(userIdLiveData) { userId ->
        Log.e("switchMap", userId)
        getUser(userId)
    }.observe(this, Observer {
        //輸出當前getUser()中返回的UserLiveData的值
         Log.e("userLiveData", it)
    })

輸出結果:

E/switchMap: 9320
E/userLiveData: link-9320
E/switchMap: 7116
E/userLiveData: link-7116

通過上面例子我們可以看到,不管需要查找多少個用戶的LiveData,界面都只需要觀察生成的LiveData一次即可。

  • MediatorLiveData

如果map和switchMap都不能滿足你對數據格式轉換的需求,那么還可以使用MediatorLiveData進行自定義的數據轉換。

MediatorLiveData是LiveData的一個子類,它可以添加或者移除多個源LiveData對象,將多個源LiveData對象組合一個單一的LiveData對象。任何LiveData源對象發生改變后,MediatorLiveData的Observer都會被觸發。

上面的map和switchMap的底層實現實際上也是使用了MediatorLiveData,我們可以簡單看一下map的源碼,來對MediatorLiveData的使用又一個大致的了解。

    @MainThread
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

MediatorLiveData的使用暫時先不介紹,我們只需要對它有個大致的了解,具體的細節,會在后續的文章中介紹。

總結

本篇文章的簡要介紹了LiveData是什么,以及如何使用LiveData。其實只要記住LiveData本質上就是一個可以感知生命周期的數據持有類,支持觀察者模式,就可以了,其他的細節幾乎都是對其特性的擴展。當我們記牢LiveData的特性后,或許就不會在開發中產生“我為毛要使用LiveData”的疑問了。

在AAC架構中LiveData和ViewModel占據了很重要的位置,下一篇我們再來介紹ViewModel。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容