LiveData源碼解析

  • LiveData is a data holder class that can be observed within a given lifecycle.
    正如注釋所說,LiveData是一個(gè)數(shù)據(jù)持有容器辱挥,并且該容器可以感知生命周期的變化,在合適的時(shí)機(jī)通知觀察者數(shù)據(jù)的變更啊央。

  • 首先定義幾個(gè)名詞眶诈,LifecycleOwner owner這里暫且稱之為生命周期感知者,簡(jiǎn)稱感知者吧瓜饥,Observer<? super T> observer是外部傳入的回調(diào)接口逝撬,內(nèi)部會(huì)被包裝成ObserverWrapper,在此稱之為觀察者乓土。

  • LiveData是一個(gè)抽象類宪潮,其子類常用的有MutableLiveDataMediatorLiveDataRoomTrackingLiveData趣苏。繼承關(guān)系如下:
public abstract class LiveData<T> {}

// 只是開放了postValue(T value)和setValue(T value)數(shù)據(jù)操作方法
public class MutableLiveData<T> extends LiveData<T> {}

// 依賴監(jiān)聽其他或多個(gè)LiveData的變化
public class MediatorLiveData<T> extends MutableLiveData<T> {}

// Room Database框架狡相,暫不分析
class RoomTrackingLiveData<T> extends LiveData<T> {}


  • 一般情況下,首先會(huì)構(gòu)造一個(gè)LiveData對(duì)象食磕,然后注冊(cè)一個(gè)LifecycleOwner生命周期感知者(一般是Fragment或者Activity)和數(shù)據(jù)變化通知的回調(diào)接口尽棕,內(nèi)部把回調(diào)接口包裝成觀察者ObserverWrapper
一般請(qǐng)用步驟:
    LiveData<User> liveData = new MutableLiveData();
    liveData.observe(this, new Observer<User>() {
        @Override
        public void onChanged(User user) {
            // do something with the newest data    
        }
    });

<LiveData.java>
    static final int START_VERSION = -1;
    private int mVersion;// 這個(gè)值是用于判斷是否已經(jīng)通知過,保證每次通知都是最新的數(shù)據(jù)值

    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;// 默認(rèn)0開始彬伦,因?yàn)樵摌?gòu)造默認(rèn)已經(jīng)將數(shù)據(jù)賦值
    }

    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;// 默認(rèn)-1開始
    }
  • 注意observe必須在主線程調(diào)用滔悉,接著看下observe方法中的實(shí)現(xiàn):
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        // 檢查是否在主線程
        assertMainThread("observe");
        // 如果當(dāng)前感知者的生命周期處于Destroy狀態(tài),直接忽略
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        // 將感知者和回調(diào)接口包裝成觀察者對(duì)象单绑,具備感知生命周期和觸發(fā)外部回調(diào)的功能
        // 生命周期感知也是一種觀察者模型
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 一種類似Map的數(shù)據(jù)結(jié)構(gòu)回官,緩存當(dāng)前觀察者
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // 一個(gè)回調(diào)接口只能綁定一個(gè)觀察者
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        // 同一個(gè)觀察者只能添加一次
        if (existing != null) {
            return;
        }
        // 添加生命周期監(jiān)聽
        owner.getLifecycle().addObserver(wrapper);
    }
  • 這個(gè)LifecycleBoundObserver觀察者中實(shí)現(xiàn)了LifecycleObserver,具備生命周期的感知能力:
    // 對(duì)生命周期變化觀察者的封裝
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        // 感知者
        @NonNull
        final LifecycleOwner mOwner;

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

        // 生命周期在onStart之后才會(huì)被標(biāo)記為激活狀態(tài)
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        // 生命周期狀態(tài)變更回調(diào)
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            // 如果感知者的生命周期進(jìn)入destroy搂橙,則移除該觀察者(同時(shí)釋放了該感知者)歉提,避免內(nèi)存泄漏
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            // 通知狀態(tài)變更(改變父類的mActive變量值),在分發(fā)通知時(shí)會(huì)用于判斷
            activeStateChanged(shouldBeActive());
        }

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

        @Override
        void detachObserver() {
            // 移除生命周期監(jiān)聽
            mOwner.getLifecycle().removeObserver(this);
        }
    }

    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;// 是否可見激活狀態(tài)
        int mLastVersion = START_VERSION;

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

        abstract boolean shouldBeActive();// 是否被激活份氧,LifecycleBoundObserver中onStart之后為true

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        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);
            }
        }
    }
  • 接著,如果我們需要改變LiveData中的數(shù)據(jù)時(shí)弯屈,只需調(diào)用其setValue或者postValue方法:
    // 緩存數(shù)據(jù)對(duì)象
    private volatile Object mData;

    // setValue只能在主線程調(diào)用
    @MainThread
    protected void setValue(T value) {
        // 判斷線程
        assertMainThread("setValue");
        // 標(biāo)記操作數(shù)
        mVersion++;
        // 賦值數(shù)據(jù)
        mData = value;
        // 分發(fā)通知各個(gè)觀察者
        dispatchingValue(null);
    }

    // 只是切換線程的作用蜗帜,可以在子線程調(diào)用
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            // 緩存當(dāng)前改變的數(shù)據(jù)
            // 在runnable中會(huì)重新標(biāo)記為NOT_SET,避免并發(fā)問題
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        // 該runnable最終還是會(huì)調(diào)用setValue
        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);
        }
    };
  • 典型的觀察者模式资厉,接下去就是通知各個(gè)觀察者數(shù)據(jù)的變化了:

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        // mDispatchingValue第一次默認(rèn)false
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        // mDispatchingValue賦值true
        // 此時(shí)如果下一次setValue觸發(fā)厅缺,上面的mDispatchInvalidated變?yōu)閠rue,下面for循環(huán)打斷退出宴偿,并且重新執(zhí)行do-while循環(huán)湘捎,這樣就能保證再次分發(fā)通知是最新的數(shù)據(jù)值(這幾個(gè)標(biāo)記的boolean變量主要也是處理并發(fā)問題)
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;// 默認(rèn)只會(huì)執(zhí)行一次do-while循環(huán)
            if (initiator != null) {
                // 當(dāng)一個(gè)observer從非激活到激活狀態(tài)時(shí)會(huì)進(jìn)入該分支
                // 該分支只會(huì)通知該observer
                considerNotify(initiator);
                initiator = null;
            } else {
                // 一般進(jìn)入該分支
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    // 遍歷取出集合中的ObserverWrapper進(jìn)行通知
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {// 如果數(shù)據(jù)在遍歷期間有新的變更,則后面未通知到觀察者不再通知
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

    // 通知觀察者數(shù)據(jù)變化
    private void considerNotify(ObserverWrapper observer) {
        // 觀察者是否處于生命周期可見狀態(tài)窄刘,mActive默認(rèn)為false不進(jìn)行通知窥妇,但是在LifecycleObserver生命周期onStart之后會(huì)賦值true
        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.
        // 再次檢查observer的生命周期是否onStart之后
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // mLastVersion默認(rèn)為-1,一般mVersion在LiveData的構(gòu)造方法中賦值-1
        // 另外一個(gè)構(gòu)造中賦值0娩践,在setValue中會(huì)++變?yōu)?或者1
        // 保證同一個(gè)observer對(duì)象對(duì)該次數(shù)據(jù)變化只能接收一次通知
        if (observer.mLastVersion >= mVersion) {
            // 如果version相等活翩,表示該數(shù)據(jù)已經(jīng)通知過了
            return;
        }
        // 標(biāo)識(shí)該次數(shù)據(jù)變化已經(jīng)通知過了
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        // 回調(diào)通知
        observer.mObserver.onChanged((T) mData);
    }

    // 對(duì)于從非激活狀態(tài)到激活狀態(tài)烹骨,會(huì)主動(dòng)請(qǐng)求接收通知
    private abstract class ObserverWrapper {
        ...
        
        void activeStateChanged(boolean newActive) {
            // 生命周期狀態(tài)沒變,忽略
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            // 是否不存在激活狀態(tài)的observer
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            // 如果observer生命周期激活狀態(tài)材泄,激活的observer數(shù)量+1沮焕,否則-1
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            // 一般情況可以忽略該判斷
            if (wasInactive && mActive) {
                onActive();// 回調(diào)通知,MediatorLiveData中有實(shí)現(xiàn)
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();// 回調(diào)通知拉宗,MediatorLiveData中有實(shí)現(xiàn)
            }
            // 如果從未激活到激活峦树,會(huì)重新分發(fā)一次
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }
  • 代碼不多,內(nèi)部就是一個(gè)典型的觀察者模型旦事,主要核心是在通知觀察者的過程中引入了生命周期的感知魁巩,對(duì)于處于激活狀態(tài)的observer才進(jìn)行通知更新,當(dāng)observer從非激活到激活狀態(tài)也會(huì)收到通知族檬。重點(diǎn)是在observer生命周期結(jié)束(Destroy)時(shí)歪赢,會(huì)自動(dòng)釋放observer的引用,從而避免了內(nèi)存泄漏单料。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末埋凯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子扫尖,更是在濱河造成了極大的恐慌白对,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件换怖,死亡現(xiàn)場(chǎng)離奇詭異甩恼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)沉颂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門条摸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人铸屉,你說我怎么就攤上這事钉蒲。” “怎么了彻坛?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵顷啼,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我昌屉,道長(zhǎng)钙蒙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任间驮,我火速辦了婚禮躬厌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘竞帽。我一直安慰自己烤咧,他們只是感情好偏陪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著煮嫌,像睡著了一般笛谦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昌阿,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天饥脑,我揣著相機(jī)與錄音,去河邊找鬼懦冰。 笑死灶轰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的刷钢。 我是一名探鬼主播笋颤,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼内地!你這毒婦竟也來了伴澄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤阱缓,失蹤者是張志新(化名)和其女友劉穎非凌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荆针,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡敞嗡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了航背。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喉悴。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖玖媚,靈堂內(nèi)的尸體忽然破棺而出箕肃,到底是詐尸還是另有隱情,我是刑警寧澤最盅,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布突雪,位于F島的核電站起惕,受9級(jí)特大地震影響涡贱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜惹想,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一问词、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘀粱,春花似錦激挪、人聲如沸辰狡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宛篇。三九已至,卻和暖如春薄湿,著一層夾襖步出監(jiān)牢的瞬間叫倍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工豺瘤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吆倦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓坐求,卻偏偏與公主長(zhǎng)得像蚕泽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子桥嗤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355