Lifecycle 流程分析

前言

為了幫助開發(fā)者更高效,更容易地構(gòu)建優(yōu)秀的應(yīng)用沪蓬,在 2018 Google IO 大會上跷叉,谷歌正式推出了 Android Jetpack Components 系列架構(gòu)組件营搅。本文的主題是 Lifecycle转质,它可以有效的避免內(nèi)存泄漏,和解決 Android 中生命周期常見的難題沸枯。

在最近學(xué)習(xí)官方的架構(gòu)組件時,我詢問了我的朋友哪轿,他指導(dǎo)我的學(xué)習(xí)順序為:Lifecycle - ViewModel - LiveData翔怎。我當(dāng)時很不解,直到我將源碼過了一邊,才發(fā)現(xiàn) LifecycleViewModelLiveData 組件的支撐于毙。

使用

1. 首先定義一個類實現(xiàn) LifecycleObserver 接口

class MainPresenter : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        println("MainPresenter: ON_CREATE")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy() {
        println("MainPresenter: ON_DESTROY")
    }
}

在對應(yīng)的方法添加 @OnLifecycleEvent 注解唯沮,接下來在 LifecyleOwner 中注冊觀察者介蛉。

2. 在 Activity 中注冊觀察者

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        println("MainActivity: onCreate")
        // 注冊觀察者
        lifecycle.addObserver(MainPresenter())
    }
}

簡單的 2 步操作溶褪,我們的 MainPresenter 就可以感知當(dāng)前 Activity 的生命周期猿妈。

2018-12-06 20:05:50.199 22452-22452/com.i3kmsteady.jetpacksample I/System.out: MainActivity: onCreate
2018-12-06 20:05:50.214 22452-22452/com.i3kmsteady.jetpacksample I/System.out: MainPresenter: ON_CREATE

2018-12-06 20:06:03.159 22452-22452/com.i3kmsteady.jetpacksample I/System.out: MainPresenter: ON_DESTROY
2018-12-06 20:06:03.161 22452-22452/com.i3kmsteady.jetpacksample I/System.out: MainActivity: onDestroy

當(dāng)然了,這只是一個簡單的實例鳍刷。在項目中的具體使用输瓜,冒昧推薦下 卻把清梅嗅MVVM-Rhine芬萍。

3. 如果在項目中使用了 Java8,推薦使用DefaultLifecycleObserver

class MainPresenter : DefaultLifecycleObserver {

    override fun onCreate(owner: LifecycleOwner) {
        super.onCreate(owner)
    }
}

大概率會遇到以下錯誤:

Super calls to Java default methods are prohibited in JVM target 1.6. Recompile with '-jvm-target 1.8'

在 app 下的 build.gradle 中的 android 閉包中添加以下代碼即可解決:

 kotlinOptions{
        jvmTarget = '1.8'
    }

雖然代碼實現(xiàn)很簡單芹缔,但是我們要保持好奇心最欠,去探究下 Lifecycle 組件的具體實現(xiàn)。

源碼分析

MainActivity 中的代碼展開蚜点,來探索一步一步的實現(xiàn)拌阴。

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 添加觀察者
        lifecycle.addObserver(MainPresenter())
    }

1. LifecycleOwner

LifecycleOwner 是描述 Android生命周期持有者的一個類迟赃。以 Activiy 為例來展開

@RestrictTo({Scope.LIBRARY_GROUP})
public class SupportActivity extends Activity implements LifecycleOwner, Component {
 
    ... 
    
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
    }

    @CallSuper
    protected void onSaveInstanceState(Bundle outState) {
        this.mLifecycleRegistry.markState(State.CREATED);
        super.onSaveInstanceState(outState);
    }

    @RestrictTo({Scope.LIBRARY_GROUP})
    public <T extends SupportActivity.ExtraData> T getExtraData(Class<T> extraDataClass) {
        return (SupportActivity.ExtraData)this.mExtraDataMap.get(extraDataClass);
    }

    public Lifecycle getLifecycle() {
        return this.mLifecycleRegistry;
    }
    ...
}

lifecycle 返回的是在 SupprotActivity 中初始化的 LifecycleRegistery 對象左刽。

2. Lifecycle

Lifecycle 是表示 Android 生命周期及其狀態(tài)的對象欠痴,具體實現(xiàn)為 LifecycleRegistery 對象。讓我們看下 addObserver()

 @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

        if (previous != null) {
            return;
        }
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            // it is null we should be destroyed. Fallback quickly
            return;
        }

        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            // mState / subling may have been changed recalculate
            targetState = calculateTargetState(observer);
        }

        if (!isReentrance) {
            // we do sync only on the top level.
            sync();
        }
        mAddingObserverCounter--;
    }

到這一步,似乎自定義的 LifecycleObserver 還是無法感知生命周期菩咨〉┪回過頭去看下 SupportActivity 中的 onCreate()雏亚,發(fā)現(xiàn)了 ReportFragment 的身影罢低。

3. ReportFragment

ReportFragment 是一個不可見的 Fragment网持,注入在 SupprotActivity 中功舀。通過 Fragment 去感知生命周期,然后通知到 LifecycleObserver()列敲。這樣就可以獲取到當(dāng)前的生命周期。以下是ReportFragment 中生命周期的分發(fā)過程

   ... 
  @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        // 生命周期分發(fā)
        dispatch(Lifecycle.Event.ON_CREATE);
    }
   ...

接下來看下 dispatch() 的實現(xiàn)

private void dispatch(Lifecycle.Event event) {
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }

        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

然后調(diào)用 LifecyclehandleLifecycleEvent 去分發(fā)生命周期凑术。

4. LifecyleRegistery

LifecyleRegisteryLifecycle 的實現(xiàn)淮逊,通過調(diào)用 handleLifecycleEvent() 去通知 LifecycleObsever 生命周期發(fā)生了變化扶踊。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
        State next = getStateAfter(event);
        moveToState(next);
    }

5. ObserverWithState

ObserverWithStateLifecyleRegistery 的靜態(tài)內(nèi)部類,調(diào)用 dispatchEvent() 去通知 LifecycleObserver备籽。

 void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }

通過 debug 調(diào)試,發(fā)現(xiàn) mLifecycleObserver 的最終實現(xiàn)是 ReflectiveGenericLifecycleObserver杂抽。

6. ReflectiveGenericLifecycleObserver

ReflectiveGenericLifecycleObserverGenericLifecycleObserver 的實現(xiàn)類缩麸。onStateChanged() 最終會調(diào)用到 CallbackInfoinvokeCallbacks()。在其內(nèi)部通過反射杭朱,解析 OnLifecycleEvent注解弧械,通知到我們所聲明的OnLifecycleEvent注解的方法上刃唐。

結(jié)語

到此画饥,Lifecycle 的基本流程就已經(jīng)過了一邊。筆者并沒有對源碼展開一步步的分析浊猾,而是從大體上出發(fā)抖甘,對代碼的具體實現(xiàn)還有勞大家私下進(jìn)一步的學(xué)習(xí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末葫慎,一起剝皮案震驚了整個濱河市衔彻,隨后出現(xiàn)的幾起案子薇宠,更是在濱河造成了極大的恐慌,老刑警劉巖米奸,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昼接,死亡現(xiàn)場離奇詭異,居然都是意外死亡悴晰,警方通過查閱死者的電腦和手機慢睡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來铡溪,“玉大人棕硫,你說我怎么就攤上這事纬纪“忻恚” “怎么了护姆?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵渐裂,是天一觀的道長。 經(jīng)常有香客問我膝捞,道長,這世上最難降的妖魔是什么盖奈? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任爹凹,我火速辦了婚禮绘趋,結(jié)果婚禮上滓走,老公的妹妹穿的比我還像新娘茬斧。我一直安慰自己,他們只是感情好娄蔼,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布涕癣。 她就那樣靜靜地躺著,像睡著了一般音比。 火紅的嫁衣襯著肌膚如雪明肮。 梳的紋絲不亂的頭發(fā)上循未,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音,去河邊找鬼宽涌。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的溶诞。 我是一名探鬼主播甩苛,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼墨林,長吁一口氣:“原來是場噩夢啊……” “哼酌呆!你這毒婦竟也來了菩收?” 一聲冷哼從身側(cè)響起箱舞,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哪廓,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡杏节,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年充坑,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邓夕,到底是詐尸還是另有隱情抢肛,我是刑警寧澤福稳,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站娱节,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏稠歉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望导梆。 院中可真熱鬧看尼,春花似錦狰域、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至好啰,卻和暖如春坎怪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背廓握。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工搅窿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人隙券。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓男应,卻偏偏與公主長得像,于是被迫代替她去往敵國和親娱仔。 傳聞我的和親對象是個殘疾皇子沐飘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355