Android livedata 源碼解剖

說在前面

本次推出 Android Architecture Components 系列文章,目前寫好了四篇,主要是關於 lifecycle,livedata 的使用和源碼分析,其他的 Navigation, Paging library,Room,WorkMannager 等春節結束以後會更新,歡迎關注個人公衆號,有更新的話會第一時間會在公衆號上面通知。javascript

Android lifecycle 使用詳解java

Android LiveData 使用詳解git

Android lifecyle 源碼解剖github

Android livedata 源碼解剖緩存

github sample 地址: ArchiteComponentsSamplebash

Android 技術人,一位不羈的碼農。app

Android 技術人


前言

在前面三篇博客中,咱們已經介紹了 lifecycle 的使用及原理,livedata ,ViewModel 的經常使用用法,今天,讓咱們一塊兒來學習 livedata 的原理。ide

咱們先來回顧一下 LiveData 的特色:源碼分析

LiveData 是一個能夠被觀察的數據持有類,它能夠感知 Activity、Fragment或Service 等組件的生命週期。post

  1. 它能夠作到在組件處於激活狀態的時候纔會回調相應的方法,從而刷新相應的 UI。
  2. 不用擔憂發生內存泄漏
  3. 當 config 致使 activity 從新建立的時候,不須要手動取處理數據的儲存和恢復。內部已經幫咱們封裝好了。
  4. 當 Actiivty 不是處於激活狀態的時候,若是你想 livedata setValue 以後當即回調 obsever 的 onChange 方法,而不是等到 Activity 處於激活狀態的時候纔回調 obsever 的 onChange 方法,你可使用 observeForever 方法,可是你必須在 onDestroy 的時候 removeObserver

下面,讓咱們一步步解剖它


原理分析

咱們知道 livedata 的使用很簡單,它是採用觀察者模式實現的

  1. 添加觀察者
  2. 在數據改變的時候設置 value,這樣會回調 Observer 的 onChanged 方法
MutableLiveData<String> nameEvent = mTestViewModel.getNameEvent();
nameEvent.observe(this, new Observer<String>() {
    @Override
    public void onChanged(@Nullable String s) {
        Log.i(TAG, "onChanged: s = " + s);
        mTvName.setText(s);
    }
});
複製代碼

observe 方法

@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);
	// observer 已經添加過了,而且緩存的 observer 跟 owner 的 observer 不一致,狀態異常,拋出異常
    if (existing != null && !existing.isAttachedTo(owner)) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
	// 已經添加過 Observer 了,返回回去
    if (existing != null) {
        return;
    }
	
	// 添加 observer
    owner.getLifecycle().addObserver(wrapper);
}

複製代碼

首先,咱們先來看一下它的 observe 方法,首先經過 owner.getLifecycle().getCurrentState() 獲取狀態,判斷是否已經被銷燬,若是已經被銷燬,直接返回。接着用 LifecycleBoundObserver 包裝起來。而後從緩存的 mObservers 中讀取 observer,若是有,證實已經添加過了。

observe 方法,小結起來就是

  1. 判斷是否已經銷燬,若是銷燬,直接移除
  2. 用 LifecycleBoundObserver 包裝傳遞進來的 observer
  3. 是否已經添加過,添加過,直接返回
  4. 將包裝後的 LifecycleBoundObserver 添加進去

所以,當 owner 你(Activity 或者 fragment) 生命週期變化的時候,會回調 LifecycleBoundObserver 的 onStateChanged 方法,onStateChanged 方法又會回調 observer 的 onChange 方法

LifecycleBoundObserver

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

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }


}

複製代碼

咱們來看一下 LifecycleBoundObserver,繼承 ObserverWrapper,實現了 GenericLifecycleObserver 接口。而 GenericLifecycleObserver 接口又實現了 LifecycleObserver 接口。 它包裝了咱們外部的 observer,有點相似於代理模式。

GenericLifecycleObserver#onStateChanged

Activity 回調週期變化的時候,會回調 onStateChanged ,會先判斷 mOwner.getLifecycle().getCurrentState() 是否已經 destroy 了,若是。已經 destroy,直接移除觀察者。這也就是爲何咱們不須要手動 remove observer 的緣由

若是不是銷燬狀態,會調用 activeStateChanged 方法 ,攜帶的參數爲 shouldBeActive() 返回的值。 而當 lifecycle 的 state 爲 started 或者 resume 的時候,shouldBeActive 方法的返回值爲 true,即表示激活。

void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    mActive = newActive;
    boolean wasInactive = LiveData.this.mActiveCount == 0;
    LiveData.this.mActiveCount += mActive ? 1 : -1;
    if (wasInactive && mActive) {
        onActive();
    }
    if (LiveData.this.mActiveCount == 0 && !mActive) {
        onInactive();
    }
    if (mActive) {
        dispatchingValue(this);
    }
複製代碼

}

activeStateChanged 方法中,,當 newActive 爲 true,而且不等於上一次的值,會增長 LiveData 的 mActiveCount 計數。接着能夠看到,onActive 會在 mActiveCount 爲 1 時觸發,onInactive 方法則只會在 mActiveCount 爲 0 時觸發。即回調 onActive 方法的時候活躍的 observer 剛好爲 1,回調 onInactive 方法的時候,沒有一個 Observer 處於激活狀態。

當 mActive 爲 true 時,會促發 dispatchingValue 方法。

dispatchingValue

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
   // 若是正在處理,直接返回
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
	
    do {
        mDispatchInvalidated = false;
		// initiator 不爲 null,調用 considerNotify 方法
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else { // 爲 null 的時候,遍歷全部的 obsever,進行分發
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
	// 分發完成,設置爲 false
    mDispatchingValue = false;
}
複製代碼

其中 mDispatchingValue, mDispatchInvalidated 只在 dispatchingValue 方法中使用,顯然這兩個變量是爲了防止重複分發相同的內容。當 initiator 不爲 null,只處理當前 observer,爲 null 的時候,遍歷全部的 obsever,進行分發

considerNotify 方法

private void considerNotify(ObserverWrapper observer) {
   // 若是狀態不是在活躍中,直接返回
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet. // // we still first check observer.active to keep it as the entrance for events. So even if // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
	

    if (observer.mLastVersion >= mVersion) {
	// 數據已是最新,返回
        return;
    }
	// 將上一次的版本號置爲最新版本號
    observer.mLastVersion = mVersion;
    //noinspection unchecked
	// 調用外部的 mObserver 的 onChange 方法
    observer.mObserver.onChanged((T) mData);
}
複製代碼
  1. 若是狀態不是在活躍中,直接返回,這也就是爲何當咱們的 Activity 處於 onPause, onStop, onDestroy 的時候,不會回調 observer 的 onChange 方法的緣由。
  2. 判斷數據是不是最新,若是是最新,返回,不處理
  3. 數據不是最新,回調 mObserver.onChanged 方法。並將 mData 傳遞過去

setValue

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

複製代碼

setValue 方法中,首先,斷言是主線程,接着 mVersion + 1; 並將 value 賦值給 mData,接着調用 dispatchingValue 方法。dispatchingValue 傳遞 null,表明處理全部 的 observer。

這個時候若是咱們依附的 activity 處於 onPause 或者 onStop 的時候,雖然在 dispatchingValue 方法中直接返回,不會調用 observer 的 onChange 方法。可是當所依附的 activity 從新回到前臺的時候,會促發 LifecycleBoundObserver onStateChange 方法,onStateChange 又會調用 dispatchingValue 方法,在該方法中,由於 mLastVersion < mVersion。因此會回調 obsever 的 onChange 方法,這也就是 LiveData 設計得比較巧妙的一個地方

同理,當 activity 處於後臺的時候,您屢次調用 livedata 的 setValue 方法,最終只會回調 livedata observer 的 onChange 方法一次。

postValue

protected void postValue(T value) {
   boolean postTask;
   // 鎖住
   synchronized (mDataLock) {
      // 當前沒有人在處理 post 任務
       postTask = mPendingData == NOT_SET;
       mPendingData = value;
   }
   if (!postTask) {
       return;
   }
   AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
   @Override
   public void run() {
       Object newValue;
       synchronized (mDataLock) {
           newValue = mPendingData;
		   // 處理完畢以後將 mPendingData 置爲 NOT_SET
           mPendingData = NOT_SET;
       }
       //noinspection unchecked
       setValue((T) newValue);
   }
};
複製代碼
  1. 首先,採用同步機制,經過 postTask = mPendingData == NOT_SET 有沒有人在處理任務。 true,沒人在處理任務, false ,有人在處理任務,有人在處理任務的話,直接返回
  2. 調用 AppToolkitTaskExecutor.getInstance().postToMainThread 到主線程執行 mPostValueRunnable 任務。
@MainThread
public void observeForever(@NonNull Observer<T> observer) {
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    wrapper.activeStateChanged(true);
}

private class AlwaysActiveObserver extends ObserverWrapper {

    AlwaysActiveObserver(Observer<T> observer) {
        super(observer);
    }

    @Override
    boolean shouldBeActive() {
        return true;
    }
}

複製代碼

由於 AlwaysActiveObserver 沒有實現 GenericLifecycleObserver 方法接口,因此在 Activity o生命週期變化的時候,不會回調 onStateChange 方法。從而也不會主動 remove 掉 observer。由於咱們的 obsever 被 remove 掉是依賴於 Activity 生命週期變化的時候,回調 GenericLifecycleObserver 的 onStateChange 方法。


總結

  1. liveData 當咱們 addObserver 的時候,會用 LifecycleBoundObserver 包裝 observer,而 LifecycleBoundObserver 能夠感應生命週期,當 activity 生命週期變化的時候,若是不是處於激活狀態,判斷是否須要 remove 生命週期,須要 remove,不須要,直接返回
  2. 當處於激活狀態的時候,會判斷是否是 mVersion最新版本,不是的話須要將上一次緩存的數據通知相應的 observer,並將 mLastVsersion 置爲最新
  3. 當咱們調用 setValue 的時候,mVersion +1,若是處於激活狀態,直接處理,若是不是處理激活狀態,返回,等到下次處於激活狀態的時候,在進行相應的處理
  4. 若是你想 livedata setValue 以後當即回調數據,而不是等到生命週期變化的時候纔回調數據,你可使用 observeForever 方法,可是你必須在 onDestroy 的時候 removeObserver。由於 AlwaysActiveObserver 沒有實現 GenericLifecycleObserver 接口,不能感應生命週期。

題外話

Android Architecture Components 已經寫了四篇文章了,其他的 Navigation, Paging library,Room,WorkMannager 等春節結束以後再更新了,歡迎關注個人公衆號,有更新的話會第一時間在公衆好上面更新。

相關文章
相關標籤/搜索