LiveData源碼解析

0.前言

關(guān)于livedata的使用詳情見LiveData+ViewModel+RxJava2+autoDisposable解決內(nèi)存泄漏,廢話也在里面古话。
啥嘚,擼起袖子擼代碼吧脱羡。

1. liveData使用

官方文檔可見定页,liveData提供了幾個(gè)方法可使用(日常使用的就四個(gè)):observer菠秒,observerForever赊瞬,postValue和setValue(省略方法的參數(shù)名),者幾個(gè)方法的區(qū)別主要如下:

  • observer用于訂閱觀察者椭岩,實(shí)現(xiàn)在Activity(LifecycleOwner)處于活躍狀態(tài)下執(zhí)行onChange方法
  • observerForever:setValue之后立馬回調(diào)onChange茅逮,不管lifeCycleOwner生命周期,需要手動(dòng)移除訂閱
  • setValue更新liveData的數(shù)據(jù)判哥,只能在UI線程調(diào)用献雅,否則報(bào)錯(cuò),liveData訂閱的Observer的onChange方法將在調(diào)用的線程中執(zhí)行
  • postValue塌计,liveData訂閱的Observer的onChange方法將在主線程中執(zhí)行挺身,內(nèi)部調(diào)用setValue(所以,這廝就是個(gè)回調(diào)方法運(yùn)行在主線程的setValue而已)

so锌仅,下面就從這幾個(gè)方法切入分析源碼
讓我們一步步揭開liveData的神秘面紗

2. observe

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        //如果owner所在Activity或Fragment處于消亡狀態(tài)下章钾,直接返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //  內(nèi)部定義的一個(gè)Observer,將owner和observer包裝起來
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
       //mObservers是緩存的SafeIterableMap热芹,繼承Iterable接口贱傀,此處判斷Observer是否已經(jīng)存在
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //如果已經(jīng)存在,且與此owner的Observer不一致伊脓,拋出異常
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //已經(jīng)存在府寒,返回
        if (existing != null) {
            return;
        }
        //否則,將包裝了owner和Observer的wrapper 添加到owner中
        //因此报腔,當(dāng)owner的生命周期發(fā)生變化時(shí)株搔,可以調(diào)用LifecycleBoundObserver 的onStateChange方法
        owner.getLifecycle().addObserver(wrapper);
    }

And Then:

  • LifecycleBoundObserver
//LifecycleBoundObserver 繼承于內(nèi)部類ObserverWrapper實(shí)現(xiàn)GenericLifecycleObserver ,實(shí)現(xiàn)onStateChanged方法
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull final LifecycleOwner mOwner;//緩存?zhèn)鬟f過來的owner

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
            super(observer);//將Observer傳給父類ObserverWrapper
            mOwner = owner;
        }

        //判斷是否需要激活纯蛾,當(dāng)生命周期為STARTED/RESUMED狀態(tài)下返回true
        //具體源碼查看lifecycle
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        //當(dāng)owner的生命周期變化時(shí)纤房,調(diào)用此方法
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                //如果已經(jīng)消亡,移除掉Observer翻诉,然后返回
                //看吧炮姨,所以我們不需要手動(dòng)移除Observer捌刮,內(nèi)部幫我們實(shí)現(xiàn)了
                removeObserver(mObserver);
                return;
            }
            //否則調(diào)用shouldBeActive判斷是否要激活狀態(tài),傳遞給activeStateChanged
            activeStateChanged(shouldBeActive());
        }

      //判斷改Observer是否已經(jīng)添加了
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
      
      //移除Observer
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

然后再調(diào)用activeStateChanged的方法進(jìn)入下一步剑令,實(shí)際上是調(diào)用父類ObserverWrapper 的activeStateChanged方法,按照“因?yàn)槎际且粯拥牟僮髀镏舨椋苑旁诟割愖詈玫牧恕边@樣的設(shè)計(jì)思想實(shí)現(xiàn)

  • ObserverWrapper
//剛才說了吁津,LifecycleBoundObserver 會(huì)包裝owner和Observer,就是這廝搞的鬼
private abstract class ObserverWrapper {
        final Observer<T> mObserver;
        boolean mActive;//記錄是否處于活躍狀態(tài)
        int mLastVersion = START_VERSION;//記錄版本號(hào)堕扶,用于判斷數(shù)據(jù)是否需要更新

        ObserverWrapper(Observer<T> observer) {
            mObserver = observer;
        }
      
        //這里不解釋
        abstract boolean shouldBeActive();
      
        //別問我碍脏,不解釋
        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }
        
        //>_<
        void detachObserver() {
        }
      
        //更新狀態(tài)(是否激活)
        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;//當(dāng)newActive為true,增加計(jì)數(shù)點(diǎn)
            //當(dāng)mActiveCount 為1時(shí)調(diào)用onActive
            if (wasInactive && mActive) {
                onActive();//這廝是個(gè)空方法
            }
            //當(dāng)mActiveCount 為0時(shí)調(diào)用稍算,所有Observer都被移除之后調(diào)用典尾,所以此方法可用于結(jié)束時(shí)釋放資源
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            //復(fù)活后更新
            //實(shí)際場(chǎng)景就是,使用setValue更新數(shù)據(jù)時(shí)糊探,activity處于瀕死狀態(tài)(onPause或onStop)時(shí)钾埂,
            //setValue調(diào)用dispatchingValue(稍后介紹)直接返回,當(dāng)Activity復(fù)活后(到前臺(tái)了)科平,就會(huì)調(diào)用此方法褥紫,從而實(shí)現(xiàn)僅在activity處于活躍狀態(tài)下更新數(shù)據(jù)
            if (mActive) {
                //處理數(shù)據(jù)
                dispatchingValue(this);
            }
        }
    }

如注釋所言,liveData只會(huì)在activity處于活躍狀態(tài)下更新數(shù)據(jù)瞪慧,看起來很神秘髓考,現(xiàn)在你知道為什么了吧,其實(shí)就是這么簡(jiǎn)單弃酌,activity復(fù)活后重新調(diào)用一次LifecycleBoundObserver 的onStateChange氨菇,然后就是activeStateChanged......

接下來是 dispatchingValue:
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //防止重復(fù)分發(fā)相同的內(nèi)容
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
          //當(dāng)initiator != null,只處理當(dāng)前Observer
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                //否則遍歷所有的Observer妓湘,進(jìn)行分發(fā)
                for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());//更新數(shù)據(jù)
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

當(dāng)initiator != null查蓉,只處理當(dāng)前Observer,否則遍歷所有的Observer榜贴,進(jìn)行分發(fā)奶是。這里怎么理解呢?怎么會(huì)有多個(gè)呢竣灌?前面也已經(jīng)說了聂沙,這還是因?yàn)閍ctivity瀕死時(shí)調(diào)用setValue多次的原因。

接下來是considerNotify:
private void considerNotify(ObserverWrapper observer) {
        //如果不處于活躍狀態(tài)初嘹,就返回
        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;
        }
        //版本號(hào)終于派上用場(chǎng)了及汉,如果數(shù)據(jù)已經(jīng)是最新,就不更新屯烦,直接返回
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);//Observer的onChanged方法終于調(diào)用了
    }

這里最后時(shí)調(diào)用了onChanged方法更新數(shù)據(jù)坷随。初次自制流程圖房铭,圖片太大勿噴

observe.png

3.setValue

@MainThread
    protected void setValue(T value) {
        //一開頭就要求運(yùn)行在主線程
        assertMainThread("setValue");
        mVersion++;//版本號(hào)更新
        mData = value;//緩存數(shù)據(jù)
        dispatchingValue(null);//什么啊,還是調(diào)用dispatchingValue呀
    }

然后就調(diào)用了dispatchingValue方法温眉,前面已經(jīng)介紹了缸匪,先介紹observe,沒毛病

setValue.png

4.postValue

protected void postValue(T value) {
        boolean postTask;
        //進(jìn)程鎖住类溢,因此liveData是線程安全的
        synchronized (mDataLock) {
          //判斷是否沒有在處理數(shù)據(jù)
            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);//實(shí)際上調(diào)用的還是setValue方法
        }
    };
postValue.png

啥嘚啥嘚凌蔬,最后一個(gè):

5.observeForever

 @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;
        }
    }

誒多,跟observe很像闯冷,只不過用來封裝owner和observer的是AlwaysActiveObserver 砂心,而AlwaysActiveObserver 并沒有像LifecycleBoundObserver 那樣繼承于內(nèi)部類ObserverWrapper實(shí)現(xiàn)GenericLifecycleObserver,所以自然不會(huì)根據(jù)Activity的生命周期回調(diào)onStateChange方法蛇耀,當(dāng)然也就不會(huì)自動(dòng)移除observer啦辩诞,必須要手動(dòng)移除。

以上纺涤!
附上總圖:


LiveData源碼解析.jpg

6.總結(jié)

本文通過源碼分析译暂,解決了

  • liveData只在activity(lifecycleowner)處于活躍狀態(tài)下更新數(shù)據(jù)的原因
  • setValue和postValue更新數(shù)據(jù)時(shí),activity處于非活躍狀態(tài)撩炊,activity重回前臺(tái)后繼續(xù)更新數(shù)據(jù)的原因
  • liveData防止內(nèi)存泄漏的原因以及自動(dòng)移除Observer的原因

原創(chuàng)文章秧秉,轉(zhuǎn)載請(qǐng)附上http://www.reibang.com/p/943770f22470

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市衰抑,隨后出現(xiàn)的幾起案子象迎,更是在濱河造成了極大的恐慌,老刑警劉巖呛踊,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砾淌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡谭网,警方通過查閱死者的電腦和手機(jī)汪厨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愉择,“玉大人劫乱,你說我怎么就攤上這事∽短椋” “怎么了衷戈?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)层坠。 經(jīng)常有香客問我殖妇,道長(zhǎng),這世上最難降的妖魔是什么破花? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任谦趣,我火速辦了婚禮疲吸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘前鹅。我一直安慰自己摘悴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布舰绘。 她就那樣靜靜地躺著蹂喻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪除盏。 梳的紋絲不亂的頭發(fā)上叉橱,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天挫以,我揣著相機(jī)與錄音者蠕,去河邊找鬼。 笑死掐松,一個(gè)胖子當(dāng)著我的面吹牛踱侣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播大磺,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼抡句,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了杠愧?” 一聲冷哼從身側(cè)響起待榔,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎流济,沒想到半個(gè)月后锐锣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绳瘟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年雕憔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糖声。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斤彼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蘸泻,到底是詐尸還是另有隱情琉苇,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布悦施,位于F島的核電站翁潘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏歼争。R本人自食惡果不足惜拜马,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一渗勘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧俩莽,春花似錦旺坠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至出刷,卻和暖如春璧疗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背馁龟。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工崩侠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坷檩。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓却音,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親矢炼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子系瓢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355