Jetpack(一)Lifecycle和LiveData

源碼分析:JetPacks之Lifecycles原理
應(yīng)用:JetPacks之?dāng)?shù)據(jù)傳遞工具
聯(lián)系:JetPack之 LifeCycle LiveData

Lifecycle

  • Lifecycle可以有效的避免內(nèi)存泄漏和解決android生命周期的常見難題
  • Lifecycle 是一個(gè)表示android生命周期及狀態(tài)的對(duì)象
  • LivecycleOwner 用于連接有生命周期的對(duì)象亏吝,如activity,fragment
  • LivecycleObserver 用于觀察查L(zhǎng)ifecycleOwner

基本使用

Lifecycle框架使用觀察者模式實(shí)現(xiàn)觀察者監(jiān)聽被觀察者的生命周期的變化

定義被觀察者>>

通過(guò)實(shí)現(xiàn)LifecycleOwner接口

ComponentActivity.png

如上圖:我們使用activity不需要再自己寫實(shí)現(xiàn)接口的代碼

定義觀察者>>

通過(guò)實(shí)現(xiàn)LifecycleObserver接口

BasePresenter.png

通過(guò)注解在觀察者類中定義需要監(jiān)聽的生命周期

注:以下方法都會(huì)在被觀察者生命周期變化時(shí)調(diào)用
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    void onCreateX(LifecycleOwner owner) {

    }


    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStartX(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onStop(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    void onResume(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    void onPause(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    void onDestory(LifecycleOwner owner) {
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    void onAny(LifecycleOwner owner) {
    }

完成訂閱關(guān)系>>

在activity中使用

被觀察者.addObserver(觀察者)
getLifecycle().addObserver(presenter);

環(huán)境配置>>

自己引入
dependencies {
  implementation "androidx.lifecycle:lifecycle-runtime:2.0.0"
  implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
  implementation "androidx.lifecycle:lifecycle-common-java8:2.0.0"
  annotationProcessor  "androidx.lifecycle:lifecycle-compiler:2.0.0"
}

核心原理

LifecycleRegister#addObserver

看一下LifecycleRegister 類中的addObserver方法這里你會(huì)發(fā)現(xiàn)生成了一個(gè)ObserverWithState,然后放入FastSafeIterableMap里娇掏,這個(gè)類是一個(gè)自定義列表爽哎,用于保存觀察者并可在遍歷期間處理刪除/添加兴垦。

  1. AppCompatActivity

AppCompatActivity 實(shí)現(xiàn)了LifecycleOwner接口,同時(shí)持有實(shí)現(xiàn)了Lifecycle的LifecycleRegistry對(duì)象,這個(gè)對(duì)象就可以將其理解為觀察者模式中的Observable橙依,LifecycleRegistr聚合多個(gè)LifecycleObserver枣接,生命周期改變時(shí)通知LifecycleObserver進(jìn)行相應(yīng)的方法調(diào)用颂暇。

  1. ReportFragment Commponent#ReportFragment.injectIfNeededIn

AppCompatActivity 繼承的extends androidx.core.app.ComponentActivity中的onCretae方法ReportFragment.injectIfNeededIn(this);
就是在當(dāng)前的Activity里添加一個(gè)ReportFragment。

  1. ReportFragment#dispatch()

再看ReportFragment的生命周期函數(shù)
你會(huì)發(fā)現(xiàn)都調(diào)用了dispatch()方法但惶,

  1. LifecycleRegistry#handleLifecycleEvent

而dispatch()方法則會(huì)判斷Activity是否實(shí)現(xiàn)了LifecycleOwner接口耳鸯,如果實(shí)現(xiàn)了該接口就調(diào)用LifecycleRegister的handleLifecycleEvent()
這樣生命周期的狀態(tài)就會(huì)借由LifecycleRegistry通知給各個(gè)LifecycleObserver從而調(diào)用其中對(duì)應(yīng)Lifecycle.Event的方法。這種通過(guò)Fragment來(lái)感知Activity生命周期的方法其實(shí)在Glide的中也是有體現(xiàn)的膀曾。

  1. handleLifecycleEvent--->getStateAfter

回到handleLifecycleEvent方法中
State next = getStateAfter(event);
事件發(fā)生的時(shí)候县爬,先得到當(dāng)前activity應(yīng)該出現(xiàn)的下一個(gè)狀態(tài)

  1. 狀態(tài)機(jī)流轉(zhuǎn)

moveToState(next);
mState = next;更新現(xiàn)在的狀態(tài)
sync();
backwardPass(lifecycleOwner);逆推
forwardPass(lifecycleOwner);

state.png
  1. forwardPass(lifecycleOwner)

forwardPass(lifecycleOwner)方法中的細(xì)節(jié)
ObserverWithState observer = entry.getValue();
找到ObserverWithState 類
調(diào)用mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
生成觀察者適配器

  1. onStateChanged

接下來(lái)就是調(diào)用onStateChanged(),來(lái)通知 實(shí)現(xiàn)了 LifecycleObserver的類,生命周期發(fā)生了變化

  1. ReflectiveGenericLifecycleObserver

查看實(shí)現(xiàn)類
ReflectiveGenericLifecycleObserver添谊。onStateChanged()

ReflectiveGenericLifecycleObserver财喳。的構(gòu)造方法中就把presenter中的方法和注解保存了下來(lái)
再通過(guò)onStateChanged()進(jìn)行生命周期的方法的調(diào)用

源碼分析 JetPacks之Lifecycles原理

應(yīng)用 JetPacks之?dāng)?shù)據(jù)傳遞工具

Demo JetPack之 LifeCycle LiveData

LiveData

LiveData是一種具有生命周期感知能力的可觀察數(shù)據(jù)持有類
LiveData可以保證屏幕上的顯示內(nèi)容和數(shù)據(jù)一直保持同步
特點(diǎn):
1.LiveData了解UI界面的狀態(tài),如果activity不在屏幕上顯示斩狱,livedata不會(huì)觸發(fā)沒必要的界面更新耳高,如果activity已經(jīng)被銷毀,會(huì)自動(dòng)清空與observer的連接所踊,意外的調(diào)用就不會(huì)發(fā)生
2.LiveData是一個(gè)LifecycleOwner,他可以直接感知activity或fragment的生命周期

基本使用

定義LifeData >>

項(xiàng)目中l(wèi)ivedata一般都存放在ViewModel中祝高,以保證app配置變更時(shí),數(shù)據(jù)不會(huì)丟失

舉個(gè)例子:

public class NameViewModel extends ViewModel {
    public int i = 0;
    private MutableLiveData<String> currentName;
    public MutableLiveData<String> getCurrentName(){
        if(currentName==null){
            currentName=new MutableLiveData<>();
        }
        return currentName;
    }
}

使用流程 >>

定義觀察者用以觀察livedata中的數(shù)據(jù)變化

//需要一個(gè)觀察者來(lái)觀察數(shù)據(jù)
        Observer observer=new Observer<String>(){
            @Override
            public void onChanged(String s) {
                nameTextView.setText(s);
            }
        };

livedata訂閱observer

        //獲取到viewmodel
        model= ViewModelProviders.of(this).get(NameViewModel.class);
        //取出livedata完成訂閱
        model.getCurrentName().observe(this,observer);

livedata發(fā)送消息通知observer更新數(shù)據(jù)

model.getCurrentName().setValue(anotherName);
以上代碼會(huì)回調(diào)observer中的onChanged方法

使用注意:

setValue只能在主線程運(yùn)行

postValue只能在子線程中運(yùn)行

核心原理

1.observe做為入口>>

使用LifecycleBoundObserver把觀察者和被觀察者包裝在一起
綁定wrapper作為觀察者

綁定完成后污筷,使用setValue與postValue通知觀察者

  1. setValue中 >>

-------dispatchingValue(null)
if (initiator != null)
參數(shù)傳null和不傳null的區(qū)別就是如果傳null將會(huì)通知所有的觀察者工闺,反之僅僅通知傳入的觀察者乍赫。
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
通知所有的觀察者通過(guò)遍歷 mObservers ,將所有的 ObserverWrapper 拿到陆蟆,實(shí)際上就是我們上面提到的 LifecycleBoundObserver雷厂,通知觀察者調(diào)用considerNotify()方法,這個(gè)方法就是通知的具體實(shí)現(xiàn)了叠殷。

-------considerNotify()

先用2個(gè)if判斷出被觀察者對(duì)應(yīng)的activity狀態(tài)是否為顯示
發(fā)送通知 onChanged()被調(diào)用

  1. postValue中 >>

切換線程到主線程中去執(zhí)行setValue

LiveDataEventBus

通過(guò)一個(gè)集合統(tǒng)一管理所有的LiveData
設(shè)計(jì)中的BUG:
原來(lái)的執(zhí)行順序new LiveData-->綁定observer-->setValue執(zhí)行onChanged
而我們的BUS在用時(shí)可能出現(xiàn) new LiveData-->setValue執(zhí)行onChanged-->綁定observer
處理方案改鲫,讓第一次setValue不起效即可

參考Github

LiveDataBus

package top.zcwfeng.jetpack.utils;

import androidx.lifecycle.MutableLiveData;

import java.util.HashMap;
import java.util.Map;

public class LiveDataBus {
    //存放訂閱者
    private Map<String, MutableLiveData<Object>> bus;
    private static LiveDataBus liveDataBus = new LiveDataBus();

    private LiveDataBus() {
        bus = new HashMap();
    }
    public static LiveDataBus getInstance() {
        return liveDataBus;
    }
    //注冊(cè)訂閱者
    public synchronized <T> MutableLiveData<T> with(String key, Class<T> type) {
        if(!bus.containsKey(key)){
            bus.put(key,new MutableLiveData<Object>());
        }
        return (MutableLiveData<T>)bus.get(key);
    }
}

LiveDataXBus 解除 LiveDataBus 粘性問題,某些場(chǎng)景需要

/**
 * 解除 LiveDataBus 粘性問題林束,某些場(chǎng)景需要
 */
public class LiveDataBusX {
    //存放訂閱者
    private Map<String, BusMutableLiveData<Object>> bus;

    private static LiveDataBusX liveDataBus = new LiveDataBusX();

    private LiveDataBusX() {
        bus = new HashMap<>();
    }

    public static LiveDataBusX getInstance() {
        return liveDataBus;
    }

    //注冊(cè)訂閱者像棘,(存入map) Hook前用MutableLiveData
    public synchronized <T> BusMutableLiveData<T> with(String key, Class<T> type){
        if(!bus.containsKey(key)){
            bus.put(key,new BusMutableLiveData<Object>());
        }
        return (BusMutableLiveData<T>) bus.get(key);
    }

    public static class BusMutableLiveData<T> extends MutableLiveData<T> {
        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            super.observe(owner, observer);
            hook(observer);
        }
        //在這里去改變onChange的流程
        private void hook(Observer<? super T> observer) {
            try {
                //1.得到mLastVersion
                //獲取到LiveData的類中的mObservers對(duì)象
                Class<LiveData> liveDataClass = LiveData.class;
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                mObserversField.setAccessible(true);
                //獲取到這個(gè)成員變量的對(duì)象
                Object mObserversObject = mObserversField.get(this);
                //得到map對(duì)應(yīng)的class對(duì)象
                Class<?> mObserversClass = mObserversObject.getClass();
                //獲取到mObservers對(duì)象的get方法
                Method get = mObserversClass.getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
                //執(zhí)行g(shù)et方法
                Object invokeEntry=get.invoke(mObserversObject,observer);
                //定義一個(gè)空的對(duì)象
                Object observerWraper=null;
                if(invokeEntry!=null && invokeEntry instanceof Map.Entry){
                    observerWraper=((Map.Entry)invokeEntry).getValue();
                }
                if(observerWraper==null){
                    throw new NullPointerException("observerWraper is null");
                }
                //得到ObserverWrapper的類對(duì)象  編譯擦除問題會(huì)引起多態(tài)沖突所以用getSuperclass
                Class<?> superclass = observerWraper.getClass().getSuperclass();
                Field mLastVersion = superclass.getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);
                //2.得到mVersion
                Field mVersion = liveDataClass.getDeclaredField("mVersion");
                mVersion.setAccessible(true);
                //3.把mVersion的數(shù)據(jù)填入到mLastVersion中
                Object mVersionValue=mVersion.get(this);
                mLastVersion.set(observerWraper,mVersionValue);


            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}

目錄:

Jetpack(一)Lifecycle和LiveData
JetPacks之Lifecycles原理
JetPack之 LifeCycle LiveData

Jetpack(二)之DataBinding

Jetpack(三) 之 Room 與 ViewModel
Jetpack 之 ViewModel 原理

Jetpack (四) 之 Navigation
Jetpack Navigation 原理淺析

JetPack (五)之 Paging 分頁(yè)庫(kù)

Jetpack(六) 之 WorkManager
Jetpack WorkManager 原理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市壶冒,隨后出現(xiàn)的幾起案子缕题,更是在濱河造成了極大的恐慌,老刑警劉巖胖腾,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件烟零,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡咸作,警方通過(guò)查閱死者的電腦和手機(jī)锨阿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)记罚,“玉大人墅诡,你說(shuō)我怎么就攤上這事⊥┲牵” “怎么了书斜?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)酵使。 經(jīng)常有香客問我荐吉,道長(zhǎng),這世上最難降的妖魔是什么口渔? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任样屠,我火速辦了婚禮,結(jié)果婚禮上缺脉,老公的妹妹穿的比我還像新娘痪欲。我一直安慰自己,他們只是感情好攻礼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布业踢。 她就那樣靜靜地躺著,像睡著了一般礁扮。 火紅的嫁衣襯著肌膚如雪知举。 梳的紋絲不亂的頭發(fā)上瞬沦,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音雇锡,去河邊找鬼逛钻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛锰提,可吹牛的內(nèi)容都是我干的曙痘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼立肘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼边坤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起谅年,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤茧痒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后踢故,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體文黎,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惹苗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年殿较,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桩蓉。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淋纲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出院究,到底是詐尸還是另有隱情洽瞬,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布业汰,位于F島的核電站伙窃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏样漆。R本人自食惡果不足惜为障,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望放祟。 院中可真熱鬧鳍怨,春花似錦、人聲如沸跪妥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)眉撵。三九已至侦香,卻和暖如春落塑,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鄙皇。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工芜赌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伴逸。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓缠沈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親错蝴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子洲愤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • 在《也談Android應(yīng)用架構(gòu)》中我們對(duì)MVC柬赐、MVP、MVVM進(jìn)行了詳盡的分析官紫,但還有一個(gè)問題懸而未決肛宋,那就是生...
    大大紙飛機(jī)閱讀 964評(píng)論 0 6
  • 久違的晴天,家長(zhǎng)會(huì)束世。 家長(zhǎng)大會(huì)開好到教室時(shí)酝陈,離放學(xué)已經(jīng)沒多少時(shí)間了。班主任說(shuō)已經(jīng)安排了三個(gè)家長(zhǎng)分享經(jīng)驗(yàn)毁涉。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,523評(píng)論 16 22
  • 今天感恩節(jié)哎沉帮,感謝一直在我身邊的親朋好友。感恩相遇贫堰!感恩不離不棄穆壕。 中午開了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,564評(píng)論 0 11
  • 可愛進(jìn)取其屏,孤獨(dú)成精喇勋。努力飛翔,天堂翱翔偎行。戰(zhàn)爭(zhēng)美好川背,孤獨(dú)進(jìn)取。膽大飛翔睦优,成就輝煌渗常。努力進(jìn)取,遙望汗盘,和諧家園皱碘。可愛游走...
    趙原野閱讀 2,727評(píng)論 1 1
  • 在妖界我有個(gè)名頭叫胡百曉隐孽,無(wú)論是何事癌椿,只要找到胡百曉即可有解決的辦法健蕊。因?yàn)槭侵缓偞蠹乙杂瀭饔灲形摇皟A城百曉”,...
    貓九0110閱讀 3,261評(píng)論 7 3