Android Jetpack 之 LiveData---入門使用

前言

最近在學(xué)習(xí) Google 推出的框架Jetpack,雖然目前網(wǎng)上的資料已經(jīng)很多了,但為了加深印象和邊動(dòng)手練習(xí)跟著學(xué)習(xí),所以站在了下面的巨人的肩膀上,并根據(jù)當(dāng)前最新的API 和編寫實(shí)際Demo,記錄下一些學(xué)習(xí)筆記,大部分是參考巨人們的,整理和休整,加入自己理解和更新吧,學(xué)習(xí)領(lǐng)略了Android Jetpack組件的一點(diǎn)魅力

目前學(xué)習(xí)筆記系列為:

日常鳴謝巨人

Google官方博文

CSDN 博主Alex@W

正題

LiveData 簡介

  • LiveData是一個(gè)具有生命周期感知特性的可觀察的數(shù)據(jù)保持類,使用LiveData保存數(shù)據(jù)時(shí),在每次訂閱數(shù)據(jù)更新時(shí)會(huì)自動(dòng)回調(diào)設(shè)置的觀察者從而更新數(shù)據(jù),真正的實(shí)現(xiàn)了數(shù)據(jù)驅(qū)動(dòng)的效果
  • LiveData的創(chuàng)建基本會(huì)在ViewModel中,從而使數(shù)據(jù)在界面銷毀時(shí)繼續(xù)保持
  • LiveData 認(rèn)為觀察者的生命周期處于STARTED狀態(tài)或RESUMED狀態(tài)下,表示觀察者處于活動(dòng)狀態(tài),LiveData只通知活躍的觀察者更新數(shù)據(jù)
  • 注冊一個(gè)實(shí)現(xiàn)該LifecycleOwner 接口的對象配對的觀察者,當(dāng)相應(yīng)Lifecycle對象的狀態(tài)改變?yōu)镈ESTROYED時(shí)需移除觀察者

LiveData 的簡單使用

依賴添加

    def lifecycle_version = "2.0.0"

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"

    implementation 'android.arch.lifecycle:extensions:1.1.1'

創(chuàng)建一個(gè)LiveData實(shí)例來保存某種類型的數(shù)據(jù)

class TestViewModel : ViewModel() {

    var mCurrent: MutableLiveData<String>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
}

確保存儲(chǔ)LiveData對象是在ViewModel中而不 是Activity 或 Fragment 中

創(chuàng)建一個(gè)定義onChanged()方法的Observer對象,在數(shù)據(jù)變化時(shí)回調(diào)

        // 創(chuàng)建觀察者對象
        val nameObservable = Observer<String> {
            ld_tv.text = it // onChange() 方法中的操作
        }

使用observe() 方法將觀察者對象附加到LiveData對象,這將觀察對象向LiveData對象訂閱,以便通知其更改

        // 創(chuàng)建viewModel 對象
        mModel = ViewModelProviders.of(this).get(TestViewModel::class.java)

        // mCurrent 訂閱觀察
        mModel.mCurrent!!.observe(this,nameObservable)
  1. 第一個(gè)參數(shù)傳遞的this就是LifecycleOwner 的實(shí)例,LiveData會(huì)根據(jù)Owner的聲明周期自動(dòng)作相應(yīng)的處理
  1. observe()將nameObservable作參數(shù)調(diào)用后,如果LiveData數(shù)據(jù)有值,onChange()立即調(diào)用獲取最新值
  1. 可以使用observeForever(Observer)方法注冊一個(gè)沒有關(guān)聯(lián)的生命周期所有者對象的觀察者,在這種情況下,觀察者被認(rèn)為總是活動(dòng)的,因此總是通知修改,可以刪除這些觀察員調(diào)用removeObserver(Observer) 方法

LiveData允許UI控制器觀察員訂閱更新

        //設(shè)置點(diǎn)擊事件,修改LiveData中的數(shù)據(jù)
        ld_btn.setOnClickListener{
            mModel.mCurrent!!.value = "AAAAAA"
        }

當(dāng)LiveData對象保存的數(shù)據(jù)發(fā)生變化時(shí),UI會(huì)自動(dòng)響應(yīng)更新

觀察者在從非活動(dòng)狀態(tài)變?yōu)榛顒?dòng)狀態(tài)時(shí)也會(huì)收到更新

運(yùn)行結(jié)果

點(diǎn)擊按鈕后改變LiveData的數(shù)據(jù),界面的TextView也隨之改變

擴(kuò)展LiveData

package andjun.com.mykt2019.java.livedata

import android.arch.lifecycle.LiveData
import android.content.Context
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import androidx.annotation.MainThread

/**
 *   author  : AndJun
 *   time    : 2019/3/12
 *   desc    :
 */

class MyLocationLiveData(context: Context) : LiveData<Location>() {

    private var locationManager: LocationManager? = null

    init {
        locationManager = context.getSystemService(
                Context.LOCATION_SERVICE) as LocationManager
    }

    @MainThread
    companion object {
        private var sInstance: MyLocationLiveData? = null
        fun getInstance(context: Context): MyLocationLiveData? {
            if (sInstance == null) {
                sInstance = MyLocationLiveData(context.applicationContext)
            }
            return sInstance
        }
    }

    private var listener: LocationListener = object : LocationListener {
        override fun onLocationChanged(location: Location?) {
        }

        override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?) {
            setValue(location)
        }

        override fun onProviderEnabled(provider: String?) {
        }

        override fun onProviderDisabled(provider: String?) {
        }
    }

    override fun onActive() {
        locationManager!!.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0.toLong(), 0.toFloat(), listener)
    }

    override fun onInactive() {
        locationManager!!.removeUpdates(listener)
    }

}
  • onActive() :當(dāng)LiveData對象具有活動(dòng)觀察者時(shí)調(diào)用該方法
    -** onInactive()** :當(dāng)LiveData對象沒有任何活動(dòng)觀察者時(shí)調(diào)用該方法
  • setValue(T) :方法更新LiveData實(shí)例的值,并通知任何活動(dòng)的觀察者有關(guān)更改的信息
  • postValue(T value)
    : 其實(shí)是在非主線程中更新數(shù)據(jù),其實(shí)他傳遞的Runnable中也是調(diào)用了setValue()方法,其余的操作只是通過ArchTaskExecutor和DefaultTaskExecutor將操作切換到主線程
調(diào)用流程如下:

setValue(T value) --> dispatchingValue(null) --> considerNotify(iterator.next().getValue()) --> observer.mObserver.onChanged((T) mData)

所以 這里就去到了 Observer 觀察者的回調(diào)中,去更新具體操作

上面代碼使用單例提供LocationLiveData可以在Activity和Fragment之間實(shí)現(xiàn)共享,在onActive和onInactive中完成監(jiān)聽的注冊和取消,當(dāng)位置改變時(shí)回調(diào)Listener并調(diào)用setValue()設(shè)置LiveData的值,從而自動(dòng)更新觀察者中的數(shù)據(jù)

使用擴(kuò)展LIveData

擴(kuò)展的LiveData使用和正常使用一樣,observe()方法將Fragmrnt(它是一個(gè)實(shí)例LifecycleOwner)作為第一個(gè)參數(shù)傳遞,使觀察者綁定到Fragment的生命周期,如果Lifecycle對象未處于活動(dòng)狀態(tài),則即使值發(fā)生更改,也不會(huì)調(diào)用觀察者,在之后Lifecycle的對象被Destroy后,觀察者被自動(dòng)刪除

簡易源碼分析

  • 加觀察者observe方法開始
observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
  • 從參數(shù)中看到了LifecycleOwner,看到 從參數(shù)中看到了LifecycleOwner 應(yīng)該會(huì)想到這里的作用是處理生命周期改變(可以參考Lifecy 使用,源碼分析),在observe方法中執(zhí)行了以下邏輯
  1. 在observe中首先判斷了當(dāng)前Lifecycler的狀態(tài),當(dāng)Destroy時(shí)即觀察者不處于活躍狀態(tài),不用接收數(shù)據(jù)

  2. 創(chuàng)建LifecycleBoundObserver實(shí)例保存?zhèn)魅氲腖ifecycleOwner和Observer,并保存在mObservers

  3. 添加LifecycleOwner的觀察者,響應(yīng)生命周期的變化

  • 在 observe 方法中的,ObserverWrapperLifecycleBoundObserver
ObserverWrapper

        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
 
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();  // 當(dāng)Owner為活躍狀態(tài)時(shí)回調(diào)onActive()
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive(); // 當(dāng)Owner未活躍狀態(tài)時(shí)回調(diào)onInactive()
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
        
        
        

LifecycleBoundObserver


        // 實(shí)現(xiàn)GenericLifecycleObserver 當(dāng)生命周期改變時(shí)回調(diào)onStateChanged
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver); // DESTROYED時(shí)移除觀察者
                return;
            }
            activeStateChanged(shouldBeActive());
        }
 
 
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }

ObserverWrapper 在Owner活躍狀態(tài)改變時(shí)回調(diào)onActive和onInactive方法,LifecycleBoundObserver主要利用Lifecycler的生命周期觀察者GenericLifecycleObserver,前面設(shè)置了owner.getLifecycle().addObserver(wrapper)后,當(dāng)生命周期改變時(shí)會(huì)回調(diào)onStateChange()方法,在生命周期為Destroy時(shí)移除Observer

小結(jié)

LiveData 整個(gè)過程就是兩部分

  • 一是使用LifeCycleOwner感知聲明周期的變化
  • 第二就是儲(chǔ)存并遍歷Observer,在數(shù)據(jù)改變時(shí)回調(diào)所有的觀察者
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容