01 Lifecycle架構(gòu)組件原理解析

提綱
  • 什么是Lifecycle贷祈;
  • 如何使用Lifecycle觀察宿主狀態(tài)嫂丙;
  • Fragment是如何實(shí)現(xiàn)Lifecycle的绍傲;
  • Activity是如何實(shí)現(xiàn)Lifecycle的幻枉;
  • Lifecycle是如何分發(fā)宿主狀態(tài)碰声。
什么是Lifecycle

Lifecycle是具備宿主生命周期感知能力的組件。它能持有組件(如Activity或Fragment)生命周期狀態(tài)的信息熬甫,并且允許其他觀察者監(jiān)聽(tīng)宿主的狀態(tài)胰挑。它也是Jetpack組件庫(kù)的核心基礎(chǔ),包括我們就會(huì)講到的LiveData椿肩,ViewModel組件等也都是基于它來(lái)實(shí)現(xiàn)的瞻颂。

再也不用手動(dòng)分發(fā)宿主生命周期,再也不用手動(dòng)反注冊(cè)了

Lifecycle的兩種寫(xiě)法

Lifecycle有兩種實(shí)現(xiàn)方法郑象,下面我們一一來(lái)介紹一下:
使用Lifecycle前需要先添加依賴(lài):

 //通常情況下贡这,只需要添加appcompat就可以了
api 'androidx.appcompat:appcompat:1.1.0'
 //如果想單獨(dú)使用,可引入下面這個(gè)依賴(lài)
api 'androidx.lifecycle:lifecycle-common:2.1.0'
LifecycleObserver配合注解:
//1. 自定義的LifecycleObserver觀察者厂榛,在對(duì)應(yīng)方法上用注解聲明想要觀  察的宿主的生命周期事件即可
class LocationObserver implements LifecycleObserver{
    //宿主執(zhí)行了onstart時(shí)盖矫,會(huì)分發(fā)該事件
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onStart(@NotNull LifecycleOwner owner){
      //開(kāi)啟定位
    }
  
  //宿主執(zhí)行了onstop時(shí) 會(huì)分發(fā)該事件
  @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
  void onStop(@NotNull LifecycleOwner owner){
     //停止定位
  }
 }

//2. 注冊(cè)觀察者,觀察宿主生命周期狀態(tài)變化
class MyFragment extends Fragment{
  public void onCreate(Bundle bundle){
    LocationObserver observer =new LocationObserver()
    getLifecycle().addObserver(observer);
  }
 }
LifecycleEventObserver宿主生命周期事件封裝成Lifecycle.Event
//1.源碼
public interface LifecycleEventObserver extends LifecycleObserver {
    void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
}
//2.用法 
class LocationObserver extends LifecycleEventObserver{
    @override
    void onStateChanged(LifecycleOwner source, Lifecycle.Event event){
      //需要自行判斷l(xiāng)ife-event是onstart, 還是onstop
    }
}

上面的這兩種Lifecycle寫(xiě)法老師比較推薦第二種丽惭,因?yàn)榈谝环N你雖然用注解很爽,但是如果沒(méi)有添加lifecycle-compiler這個(gè)注解處理器的話(huà)辈双,運(yùn)行時(shí)會(huì)使用反射的形式回調(diào)到對(duì)應(yīng)的方法上责掏。

Fragment是如何實(shí)現(xiàn)Lifecycle的?

使用Fragment實(shí)現(xiàn)Lifecycle需要在各個(gè)生命周期方法內(nèi)里雍LifecycleRegistry分發(fā)相應(yīng)的事件給每個(gè)觀察者湃望,以實(shí)現(xiàn)生命周期觀察的能力:

public class Fragment implements LifecycleOwner {
LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
  @Override
  public Lifecycle getLifecycle() {  
      //復(fù)寫(xiě)自L(fǎng)ifecycleOwner,所以必須new LifecycleRegistry對(duì)象返回
      return mLifecycleRegistry;
  }
  
 void performCreate(){
     mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
  }
  
 void performStart(){
     mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
  }
  .....
 void performResume(){
     mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
  }  
}
LifecycleOwner拷橘、Lifecycle、LifecycleRegistry的關(guān)系

事件在分發(fā)宿主生命期事件的流程中設(shè)計(jì)到三個(gè)分類(lèi)喜爷,我們分別來(lái)捋一捋:

  • LifecycleOwner:我們的Activity/Fragment都實(shí)現(xiàn)了該接口,用以生命它是一個(gè)能夠提供生命周期事件的宿主萄唇。同時(shí)必須復(fù)寫(xiě)getLifecycle()方法提供一個(gè)Lifecycle對(duì)象檩帐;
  • Lifecycle:是一個(gè)抽象類(lèi),里面定義了兩個(gè)枚舉State宿主的狀態(tài)另萤,Event需要分發(fā)的事件的類(lèi)型湃密;
  • LifecycleRegistry:是Lifecycle的唯一實(shí)現(xiàn)類(lèi),主要用來(lái)負(fù)責(zé)注冊(cè)O(shè)bserver四敞,以及分發(fā)宿主狀態(tài)事件給它們泛源。
Activity是如何實(shí)現(xiàn)Lifecycle的?

Activity實(shí)現(xiàn)Lifecycle需要借助于ReportFragment往Activity上添加一個(gè)fragment用以報(bào)告生命周期的變化忿危。目的是為了兼容不是集成自AppCompactActivity的場(chǎng)景达箍,同時(shí)也支持我們自定義LifecycleOwener的場(chǎng)景,注意了铺厨,這點(diǎn)面試會(huì)考6忻怠!解滓!赃磨。

public class ComponentActivity extends Activity implements LifecycleOwner{
  private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
   @NonNull
   @Override
   public Lifecycle getLifecycle() {
      return mLifecycleRegistry;
   }
  
  protected void onCreate(Bundle bundle) {
      super.onCreate(savedInstanceState);
      //往Activity上添加一個(gè)fragment,用以報(bào)告生命周期的變化
      //目的是為了兼顧不是繼承自AppCompactActivity的場(chǎng)景.
      ReportFragment.injectIfNeededIn(this); 
}
ReportFragment核心源碼

這里的實(shí)現(xiàn)其實(shí)跟Fragment中的源碼是一樣的,在各個(gè)生命周期方法內(nèi)利用LifecycleRegistry派發(fā)相應(yīng)的Lifecycle.Event事件給每個(gè)觀察者:

  public class ReportFragment extends Fragment{
    public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager =   activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) ==   null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            manager.executePendingTransactions();
      }
}
    @Override
    public void onStart() {
        super.onStart();
        dispatch(Lifecycle.Event.ON_START);
    }
    @Override
    public void onResume() {
        super.onResume();
        dispatch(Lifecycle.Event.ON_RESUME);
    }
    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
    }
    private void dispatch(Lifecycle.Event event) {
         Lifecycle lifecycle = activity.getLifecycle();
         if (lifecycle instanceof LifecycleRegistry) {
             ((LifecycleRegistry)   lifecycle).handleLifecycleEvent(event);
         }
}
宿主生命周期與宿主狀態(tài)模型圖

LifecycleRegistry在分發(fā)事件的時(shí)候會(huì)涉及到兩個(gè)概念:

  • 宿主生命周期:就是我們爛熟于心的onCreate,onStart,onResume,onPause,onStop...洼裤;
  • 宿主的狀態(tài):這個(gè)不是很好理解邻辉,這個(gè)意思是指宿主執(zhí)行了上述方法后,它處于對(duì)應(yīng)周期的生命狀態(tài)腮鞍。

從下面這張圖不難看出宿主生命周期與宿主狀態(tài)的對(duì)應(yīng)關(guān)系分裂為onCreate-Created值骇、onStart-Started、onResume-Resumed移国、onPause-Started雷客、onStop-Created、onDestroy-Destroyed桥狡,這里不用全部記住有個(gè)印象即可搅裙。

添加observer時(shí)皱卓,完整的生命周期事件分發(fā)

基于Lifecycle的特性我們?cè)谌我馍芷诜椒▋?nèi)注冊(cè)觀察者都能接受到完整的生命周期事件,比如在onResume中注冊(cè)一個(gè)觀察者部逮,它會(huì)依次收到:

LifecycleEvent.onCreate -> LifecycleEvent.onStart -> LifecycleEvent.onResume
添加Observer時(shí)完整的生命周期事件分發(fā)源碼分析

這一點(diǎn)需要掌握娜汁,面試中是肯定會(huì)考察的。但是如果沒(méi)有看過(guò)源碼是回答不上來(lái)的:

public void addObserver(@NonNull LifecycleObserver observer) {
        //添加新的Observer時(shí)兄朋,會(huì)首先根據(jù)宿主的狀態(tài)計(jì)算出它的初始狀態(tài)掐禁,只要不是在onDestroy中注冊(cè)的,它的初始狀態(tài)都是INITIALIZED
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //接著會(huì)把observer包裝成ObserverWithState颅和,這個(gè)類(lèi)主要是包含了觀察者及其狀態(tài)傅事。每個(gè)事件都會(huì)經(jīng)由這個(gè)對(duì)象類(lèi)轉(zhuǎn)發(fā),這個(gè)類(lèi)后面會(huì)來(lái)分析
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        //添加到集合,如果之前已經(jīng)添加過(guò)了峡扩,則return
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        if (previous != null) {
            return;
        }
        
        State targetState = calculateTargetState(observer);
        //這里的while循環(huán)蹭越,是實(shí)現(xiàn)上圖狀態(tài)同步與事件分發(fā)的主要邏輯
        //拿觀察者的狀態(tài)和宿主當(dāng)前狀態(tài)做比較,如果小于0教届,說(shuō)明兩者狀態(tài)還沒(méi)有對(duì)齊响鹃。
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            //接著就會(huì)分發(fā)一次相應(yīng)的事件,于此同時(shí)statefulObserver的mState對(duì)象也會(huì)被升級(jí)
            //假設(shè)是在宿主的onresume方法內(nèi)注冊(cè)的該觀察者
            //第一次:分發(fā)on_Create事件案训,觀察者狀態(tài)INIT->CREATED 
            //第二次:分發(fā)on_Start事件买置,觀察者狀態(tài)CREATED->STARTED 
            //第三次:分發(fā)on_Resume事件,觀察者狀態(tài)STARTED->RESUMED
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            //再一次計(jì)算觀察者應(yīng)該到達(dá)的狀態(tài)强霎,在下一輪循環(huán)中和宿主狀態(tài)在做比較忿项,知道兩者狀態(tài)對(duì)齊,退出循環(huán)城舞。
            targetState = calculateTargetState(observer);
        }
    }
宿主生命周期變化后相應(yīng)事件的分發(fā)

這一點(diǎn)了解即可倦卖,面試中也不會(huì)考這一部分的內(nèi)容:

public void handleLifecycleEvent(@NonNull Lifecycle.Event event){      
        //宿主的每個(gè)生命周期的變化都會(huì)分發(fā)一個(gè)對(duì)應(yīng)的Lifecycle.Event,走到這里
        //此時(shí)會(huì)根據(jù)需要分發(fā)的事件反推出 宿主當(dāng)前的狀態(tài)
        State next = getStateAfter(event);
        // moveToState方法只是將傳入的宿主新的state和前持有宿主狀態(tài)作比對(duì)椿争,然后保存一下怕膛。
        moveToState(next);
}
//如果宿主狀態(tài)有變動(dòng),則調(diào)用sync方法來(lái)完成事件的分發(fā)和觀察者狀態(tài)的同步
private void sync() {
        while (!isSynced()) {
        //如果宿主當(dāng)前轉(zhuǎn)態(tài) 小于 mObserverMap集合中最先添加的那個(gè)觀察者的狀態(tài)
        //則說(shuō)明宿主可能發(fā)生了狀態(tài)回退秦踪,比如當(dāng)前是RESUMED狀態(tài)褐捻,執(zhí)行了onPause則回退到STARTED狀態(tài)
        //此時(shí)調(diào)用backwardPass把集合中的每個(gè)一觀察者分發(fā)一個(gè)on_pause事件,并同步它的狀態(tài)椅邓。
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
        //如果宿主當(dāng)前轉(zhuǎn)態(tài) 大于 mObserverMap集合中最先添加的那個(gè)觀察者的狀態(tài)
        //則說(shuō)明宿主可能發(fā)生了狀態(tài)前進(jìn)柠逞,比如當(dāng)前是STARTED狀態(tài),執(zhí)行了onResume則前進(jìn)到RESUMED狀態(tài)
        //此時(shí)調(diào)用forwardPass把集合中的每個(gè)一觀察者分發(fā)一個(gè)on_resume事件景馁,并同步它的狀態(tài)板壮。
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
    }
ObserverWithState:持有觀察者及其狀態(tài)的內(nèi)部類(lèi)

把傳入的LifecycleObserver適配成LifecycleEventObserver,目的是為了統(tǒng)一事件的分發(fā)形式合住。

持有觀察者的狀態(tài)绰精,方便與宿主狀態(tài)做比對(duì)同步:

static class ObserverWithState {
        State mState;
        LifecycleEventObserver mLifecycleObserver;
        ObserverWithState(LifecycleObserver observer, State initialState) {
            //把傳入的LifecycleObserver適配成LifecycleEventObserver撒璧,目的是為了統(tǒng)一事件的分發(fā)形式
            //因?yàn)槲覀兦懊嫣岬接^察者有三種類(lèi)型,每種類(lèi)型接收事件的形式并不一樣,如果在分發(fā)的時(shí)候不統(tǒng)一事件分發(fā)的形式笨使,將會(huì)變得很麻煩
            //至于是如何適配轉(zhuǎn)換的卿樱,由于不是本文重點(diǎn),所以不再詳細(xì)展開(kāi)
            //但核心思想這里說(shuō)明一下硫椰,同學(xué)們自行看下就能明白
            //它會(huì)判斷傳入的observer是前面提到的那一種類(lèi)型繁调,進(jìn)而轉(zhuǎn)換成對(duì)應(yīng)的適配器類(lèi),適配器類(lèi)會(huì)對(duì)onStateChanged方法進(jìn)行適配靶草,并以相應(yīng)的方式(反射蹄胰、中轉(zhuǎn)、)把事件轉(zhuǎn)發(fā)到我們的observer上
            mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
            mState = initialState;
        }
         
        void dispatchEvent(LifecycleOwner owner, Event event) {
            //再一次根據(jù)需要分發(fā)的事件類(lèi)型反推出該觀察者的狀態(tài),這樣的好處是事件 &  狀態(tài) 一一對(duì)應(yīng)奕翔,不會(huì)出現(xiàn)跳躍裕寨。但閱讀上可能會(huì)稍微有點(diǎn)繞
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            //把事件分發(fā)給被包裝的對(duì)象,完成本次流程糠悯。
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }
總結(jié)

本篇從 三種用法+分發(fā)原理+面試考點(diǎn) 三個(gè)維度展開(kāi)對(duì)Lifecycle組件的介紹,現(xiàn)在相信同學(xué)們已經(jīng)掌握了Lifecycle的核心了妻往。Lifecycle組件是Jetpack組件庫(kù)的核心互艾,一旦跟宿主生命周期掛鉤,那可以做很多文章讯泣,后面講到的LiveData纫普、ViewModel都是基于它來(lái)實(shí)現(xiàn)的。

  • 本篇最后給同學(xué)們留下一個(gè)小作業(yè)好渠,基于Lifecycle實(shí)現(xiàn)APP前后臺(tái)切換事件觀察的能力昨稼。這個(gè)作業(yè)可以讓同學(xué)們加深對(duì)Lifecycle組件的理解
作業(yè):基于Lifecycle實(shí)現(xiàn)APP前后臺(tái)切換事件觀察的能力
class AppLifecycleOwner implements LifecycleOwner{
  LifecycleRegistry registry = new LifecycleRegistry(this)
  @override
  Lifecycle getLifecycle(){
    return  registry
  }

  void init(Application application){
    //利用application的  ActivityLifecycleCallbacks 去監(jiān)聽(tīng)每一個(gè)  Activity的onstart,onStop事件。
    //計(jì)算出可見(jiàn)的Activity數(shù)量拳锚,從而計(jì)算出當(dāng)前處于前臺(tái)還是后臺(tái)假栓。然后分發(fā)  給每個(gè)觀察者
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者霍掺。
  • 序言:七十年代末匾荆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子杆烁,更是在濱河造成了極大的恐慌牙丽,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兔魂,死亡現(xiàn)場(chǎng)離奇詭異烤芦,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)析校,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)构罗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)铜涉,“玉大人,你說(shuō)我怎么就攤上這事绰播〗驹耄” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蠢箩,是天一觀的道長(zhǎng)链蕊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)谬泌,這世上最難降的妖魔是什么滔韵? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮掌实,結(jié)果婚禮上陪蜻,老公的妹妹穿的比我還像新娘。我一直安慰自己贱鼻,他們只是感情好宴卖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著邻悬,像睡著了一般症昏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上父丰,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天肝谭,我揣著相機(jī)與錄音,去河邊找鬼蛾扇。 笑死攘烛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的镀首。 我是一名探鬼主播坟漱,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼更哄!你這毒婦竟也來(lái)了靖秩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤竖瘾,失蹤者是張志新(化名)和其女友劉穎沟突,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體捕传,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惠拭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片职辅。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡棒呛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出域携,到底是詐尸還是另有隱情簇秒,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布秀鞭,位于F島的核電站趋观,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏锋边。R本人自食惡果不足惜皱坛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望豆巨。 院中可真熱鬧剩辟,春花似錦、人聲如沸往扔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)萍膛。三九已至吭服,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卦羡,已是汗流浹背噪馏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工麦到, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绿饵,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓瓶颠,卻偏偏與公主長(zhǎng)得像拟赊,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子粹淋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355