Jetpack之LiveData分析

這是我參與8月更文挑戰的第2天,活動詳情查看:8月更文挑戰android

概述

官方docmarkdown

LiveData屬於Jetpack的架構組件,目的在於當底層數據發生更改的時候能夠通知到上層UI進行更新,配合MVVM架構使用,是很是舒服的。架構

我的對它的理解分紅兩部分:app

1.LivaData=Live+Data,Live是指它是有生命的,或者說能夠感知到生命週期的變化。Data是指它的本質仍是一個數據存儲相關的類。ide

2.實際的實現就是觀察者模型,LiveData的觀察者(如咱們在observe方法的時候傳入的匿名observer對象)是與Lifecycle對象(一般是Activity/Fragment)綁定在一塊兒的,在其處於活躍狀態(好比對應的Activity處於started,resumed)的時候,LiveData(被觀察者)的更新將會通知到觀察者(回調到onChanged方法)。oop

jetpack-livedata-1.png

用它的好處:①最重要的,LiveData做爲被觀察者能夠感知到觀察者(Activity/Fragment)的生命週期,自行去管理自身的生命週期。②如上說的,只有當Activity或者Fragment處於活躍狀態的時候,才能收到LiveData數據更新的通知,這能夠確保,數據發生更新的時候,UI的狀態也是能夠更新的。③能夠根據觀察者的生命週期變化,在觀察者銷燬後進行自我清理,避免內存泄露。④當界面從新恢復到活躍狀態或者從新建立的時候,會當即接收到最新的數據。post

用法

見官方文檔。ui

分析:

LiveData自己是一個抽象類,在Jetpack組件中惟一的子類是MutableLiveData。公開了兩個方法setValue和postValue。兩個方法用來更新LiveData的值,前者只能在主線程中調用,後者能夠在子線程中調用,經過Handler消息機制,通知到主線程更新。url

在這分析這兩個方法以前,先來看下,觀察者如何訂閱LiveData,即LiveData的observe方法:spa

// 第一個參數是Lifecycle的持有者,好比Activity、Fragment
// 第二個參數是觀察者對象,咱們通常就是直接建立一個匿名對象
public void observe(LifecycleOwner owner, Observer<T> observer) {
    // 若是觀察者在訂閱LiveData的時候已經處於destoryed狀態,直接跳過訂閱
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    // 將owner與observer封裝成LifecycleBoundObserver對象,這個對象主要封裝了
    // 對Lifecycle的生命狀態的賦值操做以及狀態改變時對觀察者進行取消訂閱的操做。
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    // mObservers是一個支持在迭代的過程當中進行更改的鏈表結構(存放Entry<K,V>),
    // 存放的是觀察者和上面的包裝對象,注意若是鏈表已經存放了某一個key爲observer的entry
    // 不是去更新這個entry而是直接返回value。
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    // 若是返回的value不是null,而後去肯定一下,這個observer的owner與新傳入的owner
    // 是否是一致的,若是一致,就表示這個觀察者已經綁定了某一個owner,不能重複綁定
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException( "Cannot add the same observer"
 + " with different lifecycles" );
    }
    // 若是返回的value不是null,可是也沒有進入上面的異常拋出
    // 那就是這一次綁定的owner是同樣的,沒有必要重複綁定相同的owner
    if (existing != null) {
        return;
    }
    // 爲owner添加生命週期觀察者,這樣wrapper,或者說observer就能夠感知到
    // owner(Activity/Fragment)的生命週期,當其生命週期發生變化的時候,
    // 能夠調用到wrapper的onStateChanged,去更新活躍狀態
    owner.getLifecycle().addObserver(wrapper);
}
複製代碼

LifecycleBoundObserver的onStateChanged方法:

public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
    // 若是組件的生命週期是銷燬狀態,那麼會自動的removeObserver移除觀察者,
    // 從而解除observer對LifecyclerOwner的引用,避免內存泄露的發生
    if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
        removeObserver(mObserver);
        return;
    }
    // 若是不是Destoryed狀態,那麼當Owner的生命週期變化時,會去更新到LiveData的活躍狀態
    activeStateChanged(shouldBeActive());
}
複製代碼

上面是對LiveData的生命狀態相關的分析,而後看下對LiveData的賦值操做。

setValue:

protected void setValue(T value) {
    assertMainThread( "setValue" );// 非主線程IllegalStateException
    mVersion++;// 標記當前data的版本
    mData = value;// 賦值data
    dispatchingValue(null);
}
複製代碼

setValue調用的dispatchingValue,傳入的是null:

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // 若是正在分發value,則直接return
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            // 後續
            considerNotify(initiator);
            initiator = null;
        } else {
            // 遍歷mObservers鏈表,去決定是否須要通知觀察者更新
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}
複製代碼

considerNotify:

private void considerNotify(ObserverWrapper observer) {
    // 若是觀察者不處於活躍狀態,則直接跳過
    if (!observer.mActive) {
        return;
    }
    // 可能出現Owner的生命週期變化了,可是LiveData並無收到相關通知,
    // 這裏主動去獲取Owner的當前(最新)生命狀態
    // shouldBeActivie在這兩種狀況下返回true
    // STARTED:對應的就是Activity生命週期的調用onStart以後,onPause以前
    // RESUMED: onResume調用以後
    if (!observer.shouldBeActive()) {
        // 若是處於Owner的生命狀態不活躍,這裏更新下
        observer.activeStateChanged(false);
        return;
    }
    // 若是最新的數據版本不大於上一次變更的版本,就是沒變化,那就直接return
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    // 更新上一次變更的版本值
    observer.mLastVersion = mVersion;
    // 會掉到observer的onChanged方法,傳入新的data
    //也就是咱們在訂閱LiveData的時候,傳入的匿名對象重寫的onChanged方法
    // 到這裏,觀察者就收到了LiveData的數據變更的通知。
    observer.mObserver.onChanged((T) mData);
}
複製代碼

postValue:

postValue用於在子線程通知主線程livedata發生了變化,代碼以下:

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        // mPendingData
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    // 將mPostValueRunnable這個任務拋到主線程執行
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
複製代碼

先看下mPostValueRunnable:

private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        // 在主線程中完成data的更新
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            // 而後恢復mPendingData爲未設置狀態
            // 其實mPendingData的做用就是輔助確保data的更新是在主線程中進行
            mPendingData = NOT_SET;
        }
        // postValue最終調用的也是setValue
        setValue((T) newValue);
    }
};
複製代碼

上面還有一點ArchTaskExecutor,這是Jetpack架構中比較獨立的一個部分,看下一點:

jetpack-livedata-2.png

TaskExecutor是抽象基類,主要定義了分別在子線程池和主線程處理Runnable的能力。

DefaultTaskExecutor是TaskExecutor的默認實現:

public class DefaultTaskExecutor extends TaskExecutor {
    private final Object mLock = new Object();
    // IO線程池是固定數量爲2的線程池
    private ExecutorService mDiskIO = Executors.newFixedThreadPool(2);
    @Nullable
    private volatile Handler mMainHandler;
    @Override
    public void executeOnDiskIO(Runnable runnable) {
        mDiskIO.execute(runnable);
    }
    @Override
    public void postToMainThread(Runnable runnable) {
        // runnable經過關聯主線程的Handler,post回主線程執行
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = new Handler(Looper.getMainLooper());
                }
            }
        }
        mMainHandler.post(runnable);
    }
    @Override
    public boolean isMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }
}
複製代碼

ArchTaskExecutor也是TaskExecutor的實現,與DefaultTaskExecutor的不一樣在於,ArchTaskExecutor的全部對任務的處理都是經過mDelegate這個TaskExecutor的代理對象來完成的,經過ArchTaskExecutor的set方法,客戶端能夠經過繼承TaskExecutor的方式,實現本身的Runnable任務處理邏輯。

@NonNull
private TaskExecutor mDelegate;// 默認實現就是mDefaultTaskExecutor
@NonNull
private TaskExecutor mDefaultTaskExecutor;// DefaultTaskExecutor實例
複製代碼
相關文章
相關標籤/搜索