Android Jetpack架構組件之 LiveData(使用、源碼篇)

一、前言

最近簡單看了下google推出的框架Jetpack,感受此框架的內容能夠對平時的開發有很大的幫助,也能夠解決不少開發中的問題,對代碼的邏輯和UI界面實現深層解耦,打造數據驅動型UI界面。java

Android Architecture組件是Android Jetpack的一部分,它們是一組庫,旨在幫助開發者設計健壯、可測試和可維護的應用程序,包含一下組件:bash

上述時Android Architecture所提供的架構組件,本文主要從使用和源碼的角度瞭解一下LiveData組件架構

二、LiveData簡介

  • LiveData是一個具備生命週期感知特性的可觀察的數據保持類,使用LiveData保存數據時,在每次訂閱或數據更新時會自動回調設置的觀察者從而更新數據,真正的實現了數據驅動的效果
  • LiveData的建立基本會在ViewModel中,從而使數據在界面銷燬時繼續保持
  • LiveData 認爲觀察者的生命週期處於STARTED狀態或RESUMED狀態下,表示觀察者處於活動狀態,LiveData只通知活躍的觀察者更新數據
  • 註冊一個實現該LifecycleOwner 接口的對象配對的觀察者,當相應Lifecycle對象的狀態改變爲DESTROYED時移除觀察者

三、LiveData的使用

  • 建立一個LiveData實例來保存某種類型的數據
class TestViewModel : ViewModel() {
    var mCurrent: MutableLiveData<String>? = null
        get() {
            if (field == null) {
                field = MutableLiveData()
            }
            return field
        }
}複製代碼
  1. 請確保存儲LiveData對象是在ViewModel中而不是活動或片斷
  • 建立一個定義onChanged()方法的Observer對象,在數據變化時回調
//建立觀察者對象
val nameObservable = Observer<String> {   // 建立觀察者對象
    textView.text = it       // 定義onChange()方法中的操做
}複製代碼
  • 使用LifecycleOwner的observe() 方法將觀察者對象附加到LiveData對象,這將觀察對象向LiveData對象訂閱,以便通知其更改
// 若是在View Model中使用,先建立ViewModel的對象
mModel = ViewModelProviders.of(this).get(TestViewModel::class.java)

// mCurrent 訂閱觀察
mModel.mCurrent!!.observe(this, nameObservable)  複製代碼
  1. 第一個參數傳遞的this就是LifecycleOwner 的實例,LiveData會根據Owner的聲明週期自動做相應的處理
  2. observe()將nameObservable做參數調用後,若是LiveData數據有值,onChange()當即調用獲取最新值
  3. 可使用observeForever(Observer)方法註冊一個沒有關聯的生命週期全部者對象的觀察者,在這種狀況下,觀察者被認爲老是活動的,所以老是通知修改,能夠刪除這些觀察員調用removeObserver(Observer) 方法
  • LiveData容許UI控制器觀察員訂閱更新
// 設置兩個點擊事件,修改LiveData中的數據
btnChange.setOnClickListener { mModel.mCurrent!!.value = "AAAAA" }
btnB.setOnClickListener { mModel.mCurrent!!.value = "BBBBB" }複製代碼
  1. 當LiveData對象保存的數據發生變化時,UI會自動響應更新
  2. 觀察者在從非活動狀態變爲活動狀態時也會收到更新
  • 運行結果:點擊按鈕後改變LiveData的數據,界面的TextView也隨之改變

四、轉換LiveData

  • Transformations.map():對存儲在LiveData對象中的值應用函數,並將結果傳播到下游
// 將返回開始示例中的 mCurrent 值的長度
var liveDataMap: LiveData<Int> = Transformations.map<String, Int>(mCurrent) { input: String -> input.length }複製代碼
  • Transformations.switchMap() :第二個參數返回 一個LiveData
var livaDataSwich : LiveData<String> = Transformations.switchMap<String,String>(mCurrent){
    input: String? ->  MutableLiveData<String>().also { it.value = input!!.toLowerCase() }
}複製代碼
  • 對上面轉換的LiveData訂閱觀察
val lowObservable = Observer<String> {
    textViewLow.text = it
}
val lengthObservable = Observer<Int> {
    textViewLength.text = it.toString()
}

mModel.liveDataMap.observe(this, lengthObservable)
mModel.livaDataSwich.observe(this, lowObservable)複製代碼


  • 使用場景
  1. 將LiveData對象分發給觀察者以前對其中存儲的值進行更改
  2. 須要LiveData根據另外一個實例的值返回其餘 實例
  3. 當基礎的LiveData改變時,轉換後的LiveData也會改變而且觸發UI更新

五、擴展LiveData

public class LocationLiveData extends LiveData<Location> {
    private static LocationLiveData sInstance;
    private LocationManager locationManager;

    @MainThread
    public static LocationLiveData get(Context context) {
        if (sInstance == null) {
            sInstance = new LocationLiveData(context.getApplicationContext());
        }
        return sInstance;
    }

    private SimpleLocationListener listener = new SimpleLocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            setValue(location);
        }
    };

    private LocationLiveData(Context context) {
        locationManager = (LocationManager) context.getSystemService(
                Context.LOCATION_SERVICE);
    }

    @Override
    protected void onActive() {
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
    }

    @Override
    protected void onInactive() {
        locationManager.removeUpdates(listener);
    }
}複製代碼
  1. onActive() :當LiveData對象具備活動觀察者時調用該方法
  2. onInactive() :當LiveData對象沒有任何活動觀察者時調用該方法
  3. setValue(T) :方法更新LiveData實例的值,並通知任何活動的觀察者有關更改的信息

上面代碼使用單例提供LocationLiveData能夠在Activity和Fragment之間實現共享,在onActive和onInactive中完成監聽的註冊和取消,當位置改變時回調Listener並調用setValue()設置LiveData的值,從而自動更新觀察者中的數據,其實前面使用的MutableLiveData也是一樣的一個擴展app

  • 使用擴展LIveData

擴展的LiveData使用和正常使用同樣,observe()方法將Fragmrnt(它是一個實例LifecycleOwner)做爲第一個參數傳遞,使觀察者綁定到Fragment的生命週期,若是Lifecycle對象未處於活動狀態,則即便值發生更改,也不會調用觀察者,在以後Lifecycle的對象被Destroy後,觀察者被自動刪除框架

六、源碼分析

  • MutableLiveData
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}
複製代碼

從代碼中能夠看出MutableLiveData知識LiveData的一個擴展類,重寫了LiveData中的抽象方法,postValue()和setValue()中也只是調用了super.postValue()和super.setValue(),也就是說全部的方法都是在LiveData中實現,ide

  • LiveData.observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }複製代碼

從第一步添加觀察者observe方法開始,從參數中看到了LifecycleOwner,相信看過Lifecycler源碼的(Android Jetpack框架之 Lifecycle(源碼篇))應該會想到這裏的做用是處理生命週期改變,在observe方法中執行了如下邏輯:函數

  1. 在observe中首先判斷了當前Lifecycler的狀態,當Destroy時即觀察者不處於活躍狀態,不用接收數據
  2. 建立LifecycleBoundObserver實例保存傳入的LifecycleOwner和Observer,並保存在mObservers
  3. 添加LifecycleOwner的觀察者,響應生命週期的變化
  • ObserverWrapper & LifecycleBoundObserver
private abstract class ObserverWrapper {
        final Observer<T> mObserver;
       
        ObserverWrapper(Observer<T> observer) {
            mObserver = observer;  // 保存觀察者Observer
        }
        
        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();  // 當Owner爲活躍狀態時回調onActive()
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive(); // 當Owner未活躍狀態時回調onInactive()
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }


 class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { // 
        @NonNull final LifecycleOwner mOwner;  //保存LifecycleOwner 

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
            super(observer); // 調用父類ObserverWrapper的構造函數傳遞Owner
            mOwner = owner;
        }

        // 實現GenericLifecycleObserver 當生命週期改變時回調onStateChanged
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver); // DESTROYED時移除觀察者
                return;
            }
            activeStateChanged(shouldBeActive());
        }


        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }複製代碼

上述執行的邏輯見代碼中的註釋,ObserverWrapper 在Owner活躍狀態改變時回調onActive和onInactive方法,LifecycleBoundObserver主要利用Lifecycler的生命週期觀察者GenericLifecycleObserver,前面設置了owner.getLifecycle().addObserver(wrapper)後,當生命週期改變時會回調onStateChange()方法,在生命週期爲Destroy時移除Observer;源碼分析

  • setValue(T value)
@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }


 private void dispatchingValue(@Nullable ObserverWrapper initiator) {

            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
    }複製代碼

setValue()中調用了dispatchingValue(),在dispatchingValue中遍歷mObservers中全部的Observer,調用considerNotify()更新數據post

  • considerNotify()
private void considerNotify(ObserverWrapper observer) {
        observer.mObserver.onChanged((T) mData);
    }複製代碼

considerNotify()中調用mObserver的onChange()方法,這裏的mObserver就是前面observe()中第二個參數的Observer,從而更新數據,簡單就是說當LiveData中的數據改變時會遍歷此LiveData全部的觀察者,並回調onChange(),因此全部註冊觀察此數據的地方都會改變測試

  • postValue(T value)
protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }


private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };複製代碼

postValue()實際上是在非主線程中更新數據,其實他傳遞的Runnable中也是調用了setValue()方法,其他的操做只是經過ArchTaskExecutor和DefaultTaskExecutor將操做切換到主線程。

LiveData的使用和源碼分析到此結束了,LiveData整個過程就是兩部分,一是使用LifeCycleOwner感知聲明週期的變化,兩一個就是儲存並遍歷Observer,在數據改變時回調全部的觀察者,LiveData的實現仍是比較簡單的,但願本篇文章的分析對你們有所幫助。

相關文章
相關標籤/搜索