LiveData源碼解析

基於: macOs:10.14/AS:3.4/Android build-tools:28.0.0java

思路

看源碼前先考慮下若是要本身實現 LiveData 應該怎麼作?多線程

基本作法:app

  1. 目標數據私有;
  2. 開放 setter 方法用於更新目標數據;
  3. 提供方法添加數據變化監聽器(Observer);

擴展:ide

  1. 容許子線程更新數據, 所以 setter 須要考慮同步;
  2. 項目中可能多個地方須要用到目標數據,所以回調監聽器能夠添加多個;
  3. 數據變化時經常都須要更新UI,而UI有生命週期,所以 Observer 須要提供 Lifecycle 相關邏輯支持,包括:
    1. 定義處於哪些生命週期的 Observer 能夠收到數據更新;
    2. onDestroy() 時自動移除 Observer 等;
  4. 如何定義 數據變化 呢? 最簡單直接的作法是每次觸發 setter 方法時都看成數據發生了變化, 遍歷通知全部 Observer 便可, 更進一步的斷定交給調用方; ......

簡單使用

// 定義 livedata
object ParaConfig {
    // 定義一個私有的 `MutableLiveData`
    private val msgLiveData = MutableLiveData<String>()

    // 開放給外部獲取數據更新時,提供不可變的 `LiveData` 便可;
    fun getMsgLiveData(): LiveData<String> = msgLiveData

    fun updateMsg(msg: String, inBgThread: Boolean = false) {
        if (inBgThread) {
            msgLiveData.postValue(msg) // 在子線程中更新數據
        } else {
            msgLiveData.value = msg // 在主線程中更新數據
        }
    }
}
複製代碼
// 添加 `Observer`
class LiveDataFrag : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 添加一個跟生命週期相關的 `Observer`
        ParaConfig.getMsgLiveData().observe(this, Observer<String> { newMsg ->
            tv_msg.text = newMsg
        })

        // 無視生命週期, 每次數據變化時都會回調,須要自行移除observer
        ParaConfig.getMsgLiveData().observeForever {
            Logger.d("observeForever: $it","tag_livedata")
        }
    }
}
複製代碼

看源碼我仍是習慣從調用入口一步步往下看, 如下也是按照這種順序來;post

實現

livedata

添加 Observer

// LiveData.java
public abstract class LiveData<T> {
    private static final Object NOT_SET = new Object();
    // 實際數據,類型爲 Object 而非 T
    private volatile Object mData = NOT_SET;
    // 存儲全部的 Observer
    private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

    // 添加跟生命週期相關的 observer
    // 目標數據
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        // 若 LifecycleOwner 已處於已被銷燬,則忽略該 observer
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }

        // 將 LifecycleOwner 和 Observer 功能進行綁定包裝
        // 生成支持生命週期感知的 Observer: LifecycleBoundObserver
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 避免重複添加相同的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;
        }

        // 實現對 LifecycleOwner 生命週期的感知
        // 關鍵仍是 LifecycleBoundObserver 類,咱們立刻進去看一下
        owner.getLifecycle().addObserver(wrapper);
    }

    // 無視生命週期, 每次數據發生變化時,都會回調通知 Observer
    // 須要手動在不須要時移除 Observer
    @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);
    }
}
複製代碼

MutableLiveData 只是簡單重寫了 LiveDatasetValue(T)/postValue(T) 方法, 改成 public 而已;ui

數據如何傳遞的: setValue(T) 解析

// LiveData.java
@MainThread
protected void setValue(T value) {
    // 只能在UI線程中調用,不然拋出異常,崩潰
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

private boolean mDispatchingValue;

// 若參數 initiator 非空,則表示只通知特定的 ObserverWrapper, 不然是回調通知全部 ObserverWrapper
// 因爲只在主線程中調用,所以不用作多線程處理
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // 小技巧: 在遍歷通知各 ObserverWrapper 期間, 若數據發生了變化, 則會從新遍歷通知
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }

    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {// initiator 非空時,只更新特定 ObserverWrapper
            considerNotify(initiator); // 實際更新數據的方法
            initiator = null;
        } else { // 不然遍歷更新全部 ObserverWrapper
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                // 若數據發生變化, 則退出for循環
                // 而外層 do...while() 斷定條件爲true,就會從新遍歷通知各 ObserverWrapper;
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

// 判斷是否要將數據分發到指定的 ObserverWrapper
private void considerNotify(ObserverWrapper observer) {
    // 是否能夠分發數據到指定的 observer, 由 mActive 來控制
    // 因此 mActive 很重要,具體下一節解讀
    if (!observer.mActive) {
        return;
    }

    // 二次確認狀態, 可能生命週期發生了變化,但 mActive 並未改變
    if (!observer.shouldBeActive()) {
        // active -> inactive 時通知更新狀態
        // inactive 狀態下就不須要分發數據了
        observer.activeStateChanged(false);
        return;
    }

    // 若 ObserverWrapper 持有的數據值已經是最新版本, 天然也不用分發
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;

    // 通知 observer 數據有更新
    // observer.mObserver 是調用方實際傳入的
    observer.mObserver.onChanged((T) mData);
}
複製代碼

用於子線程調用的 postValue(T) 會發射一個 Runnable 到主線程中, 最終也是經過 setValue(T) 來實現數據分發; 固然, postValue(T) 也能夠在主線程調用,不過是畫蛇添足,如:this

// observer會先收到 "msgFromSetValue" 而後才收到 "msgFromPostValue"
someBtnView.setOnClickListener {
    msgLiveData.postValue("msgFromPostValue")
    msgLiveData.value = "msgFromSetValue"
}
複製代碼

ObserverWrapper 類解析

ObserverWrapper

// LiveData 的內部抽象類
// 包裝用戶傳入的 Observer, 提供數據版本記錄以及active狀態(生命週期)判斷
private abstract class ObserverWrapper {
    final Observer<T> mObserver;
    boolean mActive; // 肯定當前 ObserverWrapper 是否生效,true時纔可進行數據更新
    int mLastVersion = START_VERSION; // 當前持有的數據版本號,初始值爲 -1

    ObserverWrapper(Observer<T> observer) {
        mObserver = observer;
    }

    // 判斷該 Observer 是否有效, true 時纔會觸發 activeStateChanged()
    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    // 更新本 ObserverWrapper 的狀態
    void activeStateChanged(boolean newActive) {
        // 若狀態沒變化,不須要更新,直接返回
        if (newActive == mActive) {
            return;
        }

        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1;

        // 處於 active 狀態的 observer 數量從0 -> 1時,觸發 onActive() 方法
        if (wasInactive && mActive) {
            onActive();
        }

        // 處於 active 狀態的 observer 數量從 1 -> 0時,觸發 onInactive() 方法
        // 提供給觀察者釋放資源的機會
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive();
        }

        // observer 從 inactive -> active 時, 更新數據
        if (mActive) {
            // 將數據發送給該 observer
            dispatchingValue(this);
        }
    }
}
複製代碼

此類並未給出 inactive/active 具體是何種狀態, 具體應是由 shouldBeActive() 來肯定, 所以須要從子類查找;spa

子類 AlwaysActiveObserver比較簡單, 只是將shouldBeActive() 固定返回 true,表示一直生效, 每次數據發生變化時都須要發送通知; 咱們看下 LifecycleBoundObserver 類;線程

LifecycleBoundObserver 解析

// LiveData 內部類
// 將 LifecycleObserver 和 ObserverWrapper 結合,當生命週期變化時,通知 ObserverWrapper 更新數據
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull final LifecycleOwner mOwner;

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

    @Override
    boolean shouldBeActive() {
        // 此處定義了哪些生命週期是 `active` 的
        // 結合 Lifecycle.State 類 ,咱們知道是: STARTED/RESUMED 兩種狀態
        // 對應於生命週期 `onStart()` 以後到 `onStop()` 以前
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    // 生命週期變化時回調本方法
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        // 若當前 LifecycleOwner onDestory() 了, 則自動移除 observer, 避免內存泄露
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        // 將 shouldBeActive() 返回的狀態當作本 ObserverWrapper 的狀態
        // 即 mActive = shouldBeActive()
        activeStateChanged(shouldBeActive());
    }

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

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

小結

  1. 只能在主線程中進行 Observer 的添加:
    1. observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
    2. observeForever(@NonNull Observer<T> observer)
  2. 添加帶 LifecycleOwnerObserver 時, 若發生 onDestory() ,則會自動移除 Observer;
  3. 數據只會在 LifecycleOwner 處於 onStart()/onResume()/onPause() 生命週期時,纔會分發;
  4. 若處於 active 的 Observer 數量從 1 -> 0, 回調 onInactive() ,適用於子類進行資源釋放;
  5. 若處於 active 的 Observer 數量從 0 -> 1, 回調 onActive();
  6. LiveData 類和 ObserverWrapper 類都會在內部持有一個數據版本號;
  7. LiveData 數據發生變化時,會切換到主線程,而後遍歷全部 Observer, 並將數據分發給處於 active 狀態而且數據版本號不一致的 Observer;
相關文章
相關標籤/搜索