Android 架構(gòu)組件 —— Lifecycle-aware Components [三]

本文將對Lifecycle-aware Components三大組件之一的LiveData進行分析蛉签。
首先,分析一下LiveData類的結(jié)構(gòu):

LiveData類結(jié)構(gòu)

可以看出浅浮,LiveData給出的方法主要分為以下兩類:

  • 添加刪除observer
  • 更新本身存儲的數(shù)據(jù)
    接下來將對這兩個方面入手分析LiveData工作機制

添加刪除observer

添加observer有兩個方法

  1. observeForever(@NonNull Observer<T> observer)
  2. observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
    方法一是將一個生命周期不會變化(保持Lifecycle.Event.ON_RESUME狀態(tài))的LifecycleOwner作為參數(shù)調(diào)用的方法二:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // 進入DESTROYED狀態(tài)無需繼續(xù)
        return;
    }
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing != null && existing.owner != wrapper.owner) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    owner.getLifecycle().addObserver(wrapper);
}

class LifecycleBoundObserver implements GenericLifecycleObserver {
    public final LifecycleOwner owner;
    public final Observer<T> observer;
    public boolean active;
    public int lastVersion = START_VERSION;

    LifecycleBoundObserver(LifecycleOwner owner, Observer<T> observer) {
        this.owner = owner;
        this.observer = observer;
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(observer);
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == active) {
            return;
        }
        active = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += active ? 1 : -1;
        if (wasInactive && active) {
            onActive();
        }
        if (LiveData.this.mActiveCount == 0 && !active) {
            onInactive();
        }
        if (active) {
            dispatchingValue(this);
        }
    }
}

首先將observer封裝成一個LifecycleBoundObserver對象添加到mObservers中去柠偶,和前面介紹的LifecycleRegistry如出一轍别伏,之后將封裝后的observer同時注冊到對應(yīng)的LifecycleOwner中去吐根,此時依據(jù)上節(jié)內(nèi)容,LifecycleRegistry會將LifecycleBoundObserver進行進一步封裝成為ObserverWithState赠尾,在生命周期發(fā)生變化時力穗,通過調(diào)用dispatchEvent(LifecycleOwner owner, Event event)方法通知observer生命周期變更,從而讓LifecycleBoundObserver感知生命周期气嫁,在DESTROYED狀態(tài)下自動移除当窗。

刪除observer與添加邏輯相同,只是多了一步將observer激活狀態(tài)改為false寸宵,對LiveData內(nèi)部統(tǒng)計數(shù)據(jù)(mActiveCount)進行更改超全。

LiveData值的刷新

LiveData提供了兩種方法對其進行賦值:

  • setValue(T value)(主線程賦值)
  • postValue(T value)(子線程賦值)

setValue(T value)

首先先對主線程賦值進行一個了解:

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

private void dispatchingValue(@Nullable LifecycleBoundObserver initiator) {
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<T>, LifecycleBoundObserver>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

private void considerNotify(LifecycleBoundObserver observer) {
    if (!observer.active) {
        return;
    }

    if (!isActiveState(observer.owner.getLifecycle().getCurrentState())) {
        observer.activeStateChanged(false);
        return;
    }
    if (observer.lastVersion >= mVersion) {
        return;
    }
    observer.lastVersion = mVersion;
    //noinspection unchecked
    observer.observer.onChanged((T) mData);
}

主要方法在dispatchingValue(@Nullable LifecycleBoundObserver initiator)中:

  1. mDispatchingValue -> true代表之前有值刷新尚未廣播完成,將mDispatchInvalidated改為true邓馒,為false則直接向下進行嘶朱;
  2. 將mDispatchingValue設(shè)為true表示正在廣播,隨后判斷是對單個observer進行通知或者對所有監(jiān)聽此項的observer進行通知光酣。此時若有新值需要廣播疏遏,則在對所有監(jiān)聽此項observer進行通知時直接退出重新遍歷發(fā)送最新值。
    considerNotify(LifecycleBoundObserver observer)方法則是根據(jù)當(dāng)前項的激活狀態(tài)決定是移除observer還是將值變化通知對應(yīng)observer進行改變救军。

postValue(T value)

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        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);
    }
};

postValue(T value)則是先暫時將新值保存财异,隨后將具體調(diào)用setValue方法post到一個依附于主線程的Handle中去,通過Handle達到線程切換目的從而通知值刷新唱遭。

使用

LiveData使用時主要是使用子類MutableLiveData戳寸,這個子類實現(xiàn)了Livedata并公開了兩個賦值方法。

小結(jié)

LiveData的工作流程在有了之前LifecycleRegistry的分析之后變得很清晰:主要是將observer封裝后存儲拷泽,并依托LifecycleRegistry根據(jù)生命周期和自身值變化達到刷新通知observer進行刷新目的疫鹊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末袖瞻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子拆吆,更是在濱河造成了極大的恐慌聋迎,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枣耀,死亡現(xiàn)場離奇詭異霉晕,居然都是意外死亡,警方通過查閱死者的電腦和手機捞奕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進店門牺堰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人颅围,你說我怎么就攤上這事伟葫。” “怎么了谷浅?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵扒俯,是天一觀的道長奶卓。 經(jīng)常有香客問我一疯,道長,這世上最難降的妖魔是什么夺姑? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任墩邀,我火速辦了婚禮,結(jié)果婚禮上盏浙,老公的妹妹穿的比我還像新娘眉睹。我一直安慰自己,他們只是感情好废膘,可當(dāng)我...
    茶點故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布竹海。 她就那樣靜靜地躺著,像睡著了一般丐黄。 火紅的嫁衣襯著肌膚如雪斋配。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天灌闺,我揣著相機與錄音艰争,去河邊找鬼。 笑死桂对,一個胖子當(dāng)著我的面吹牛甩卓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蕉斜,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼逾柿,長吁一口氣:“原來是場噩夢啊……” “哼缀棍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鹿寻,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤睦柴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后毡熏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坦敌,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年痢法,在試婚紗的時候發(fā)現(xiàn)自己被綠了狱窘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡财搁,死狀恐怖蘸炸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情尖奔,我是刑警寧澤搭儒,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站提茁,受9級特大地震影響淹禾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜茴扁,卻給世界環(huán)境...
    茶點故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一铃岔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧峭火,春花似錦毁习、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稍浆,卻和暖如春载碌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粹湃。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工恐仑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人为鳄。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓裳仆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孤钦。 傳聞我的和親對象是個殘疾皇子歧斟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 前言: 作為一名移動互聯(lián)網(wǎng)App研發(fā)人員纯丸,在實際項目的研發(fā)過程中,保質(zhì)保量高效率静袖,方便快捷觉鼻,同時方便開發(fā)者之間的互...
    Yagami3zZ閱讀 4,672評論 1 9
  • 前言 系列文章 Android Architecture Component之Lifecycle-Aware Co...
    Jason騎蝸牛看世界閱讀 3,507評論 3 20
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理队橙,服務(wù)發(fā)現(xiàn)坠陈,斷路器,智...
    卡卡羅2017閱讀 134,715評論 18 139
  • 示例應(yīng)用程序 使用LiveData的優(yōu)點 使用LiveData對象創(chuàng)建LiveData對象觀察LiveData對象...
    yyg閱讀 5,862評論 5 7
  • 吳賢碧 我以淺坐的姿態(tài) 著一襲白裙 以品茶的借口 在湖邊等了又等 終在秋天泛紅的那片紅葉里 等來翩然而至的你 相思...
    閑筆閱讀 967評論 0 1