一點點入坑JetPack:Lifecycle篇

zybing發表於2021-09-09

前言

因為業務的原因,自己也開始了JetPack之旅。不得不承認,用上之後:真香。 JetPack以官方的方案,解決了很多我們頭疼的問題。JetPack作為一整套的解決方案,不是一篇文章很夠解釋清楚的。正如官方所說:

Android Jetpack 元件是庫的集合,這些庫是為協同工作而構建的,不過也可以單獨採用,同時利用 Kotlin 語言功能幫助您提高工作效率。可全部使用,也可混合搭配!

所以這將是一個系列文章,一點點的展開我在JatPack應用中的所學所想。(目前公司專案已將全面用Kotlin,JetPack進行了重構,因此很多程式碼的設計會和我們的業務相結合,所以仁者見仁智者見智啦~)

一點點入坑JetPack:ViewModel篇

一點點入坑JetPack:Lifecycle篇

一點點入坑JetPack:LiveData篇

文章重點部分將聚焦:

一點點入坑JetPack:Lifecycle篇

正文

不想看我瞎比比的,也可以直接跳轉至官網:developer.android.google.cn/topic/libra…

1、如何管理生命週期

Lifecycle的出現幫我們解決生命週期管理的問題。這一塊對於我們日常開發來說的確是比較坑的一點,生命週期處理不當,很容易造成記憶體洩漏。 為了能讓我們業務程式碼能夠感知到生命週期,我們可能會寫大量的程式碼。比如在讓Presenter擁有感知生命週期的能力,我們可能會這麼做:

public interface IPresenter {
    void onCreate();

    void onStart();

    void onResume();

    void onPause();

    void onStop();

    void onDestroy();
}
複製程式碼

然後實現介面,在Activity/Fragment的生命週期中呼叫這個介面,完成工作。

這種方式完全ojbk。通俗易懂,這裡我不評價它的好壞,畢竟沒有任何一種解決方案是完美的。所以接下來我們們來看一看官方的Lifecycle是怎樣的一種思路。


2、Lifecycle

說破天,這裡需要解決的問題是生命週期管理。那麼終究還是逃脫不掉一些套路成分在其中。Lifecycle也是如此,從官方的解釋中,可見一斑:

Lifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state.

短短一段話,我們可以猜測到這裡通過觀察者模式的思路去對外響應生命週期變化。閒話少說,直接從程式碼感受一下。

2.1、使用

從使用上來說,還是比較簡單的。實現LifecycleObserver介面:

// 官方demo
class MyObserver : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun connectListener() {
        // TODO
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun disconnectListener() {
        // TODO
    }
}

複製程式碼

這倆個註解則標誌著,當監聽元件的onResume()方法被呼叫,這裡我們被註解的方法也會被呼叫。(當然前提是addObserver了)

有了觀察者了,那我們就去找被觀察者。很明顯,我們想要觀察的物件是擁有生命週期的傢伙,比如我們常用的Activity/Fragment。此時我們只需要在onResume()之前的某個實際,把這個Observer,add進去即可,比如在onCreate()中:

override fun onCreate(savedInstanceState: Bundle?) {
   lifecycle.addObserver(MyObserver())
}
複製程式碼

OK,這樣之後我們的MyObserver既可以正常在響應對應生命週期註解下的方法了。

不過,我相信這樣寫的朋友,回過來噴我!根本就調不到lifecycle!!

沒錯,我們常規的Activitiy/Fragment就是調不到...它壓根就沒這這個方法。

2.2、androidx

這裡解釋一下,上文中lifecyle其實就是呼叫Activity/Fragment中的這個方法:

@Override
public Lifecycle getLifecycle() {
    return mLifecycleRegistry;
}
複製程式碼

有朋友應該提著刀過來了,我tm沒有這個方法!兄die,把刀放下,不是沒有是import不一樣。接下來讓我們慢慢來。我使用的這個Fragment的package是這樣的:androidx.fragment.app;。看到端倪了吧?androidx,沒錯,這是為了完美支援JatPack所重新規劃出來的包。

當然,也不一定非要用androidx。

Fragments and Activities in Support Library 26.1.0 and later already implement the LifecycleOwner interface.

所以,升庫就ok了。這時有小夥伴可能會說了:我不想升庫怎麼辦。這個問題問得好,不想升庫,不想升庫..就不升唄。

當然我相信,一定有小夥伴注意到一個問題,那就是getLifecycle()是一個介面,那麼也就是說我們可以自己實現?沒錯是這樣...(這tm不廢話麼)

這就是我們自定義的關鍵。

2.3、LifecycleOwner

假設我們的Activity不支援getLifecycle()咋整?這裡直接上官方的程式碼:

class MyActivity : Activity(), LifecycleOwner {
    private lateinit var mLifecycleRegistry: LifecycleRegistry

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mLifecycleRegistry = LifecycleRegistry(this)
        mLifecycleRegistry.markState(Lifecycle.State.CREATED)
        
        mLifecycleRegistry.addObserver(MyObserver())
    }

    public override fun onStart() {
        super.onStart()
        mLifecycleRegistry.markState(Lifecycle.State.STARTED)
    }

    override fun getLifecycle(): Lifecycle {
        return mLifecycleRegistry
    }
}
複製程式碼

就這樣,結束了。說實話,到這就這的沒有什麼好講的了。

通過程式碼,我們可以看出來,LifecycleRegistry是我們的被觀察者,它被初始化在擁有生命週期的Activity中,而我們的Observer也被add()到其中,此外還有諸如markState(Lifecycle.State.CREATED)的方法呼叫。

因此,到這無需多言,各位小夥伴恐怕已經明白了Lifecycle是如何幫我們管理生命週期的了。

2.4、小總結

這幾段程式碼下來,我相信有的朋友已經差不多瞭解Lifecycle的思路了。一個很標準的觀察者模式:這裡的LifecycleRegistry(系統幫我們實現的Lifecycle的實現類),持有想要監聽這個LifecycleOwner的Observer。然後通過markState(),去遍歷所有Observer,通知其生命週期發生變化。


3、原理

聊完了普通用法,我們們來看一下原理。不得不說,Lifecycle實現的原理還是比較騷的,各種騷操作簡直是亂花漸欲迷人眼。

我們們在上述的MyObserver中加了註解,所以先看看註解為我們帶來了什麼。通過註解生成器,我們可以看到在build中得到了下邊這個class:

public class MyObserver_LifecycleAdapter implements GenericLifecycleObserver {
    final MyObserver mReceiver;

    LifecycleObserverDemo_LifecycleAdapter(MyObserver receiver) {
        this.mReceiver = receiver;
    }

    @Override
    public void onStateChanged(LifecycleOwner owner, Lifecycle.Event event) {
        mReceiver.onAny(owner,event);
        if (event == Lifecycle.Event.ON_RESUME) {
            mReceiver.connectListener();
        }

        if (event == Lifecycle.Event.ON_PAUSE) {
            mReceiver.disconnectListener();
        }
    }

    public Object getReceiver() {
        return mReceiver;
    }
}
複製程式碼

很清晰,我們能夠看到,在onStateChanged(LifecycleOwner owner, Lifecycle.Event event)中通過對應的Event就可以呼叫到我們MyObserver中註解的方法。

那麼問題來了:onStateChanged被誰呼叫的呢?通過上邊的例子,我們知道想要Observer能夠感應生命週期要麼使用內建好的Lifecycle(getLifecycle()),要麼自己去實現(LifecycleOwner)。接下來我們們就分這倆種情況來看一看具體的實現原理。

3.1、自定義LifecycleOwner

這一步的原始碼還是比較的簡單直接的,我們可以直接在LifecycleRegistry中的markState(Lifecycle.State.STARTED)一探究竟,一層層的呼叫下來,我們拋棄一些邏輯判斷之後,可以看到一些關鍵的內容:

static class ObserverWithState {
    State mState;
    GenericLifecycleObserver mLifecycleObserver;

    ObserverWithState(LifecycleObserver observer, State initialState) {
        mLifecycleObserver = Lifecycling.getCallback(observer);
        mState = initialState;
    }

    void dispatchEvent(LifecycleOwner owner, Event event) {
        State newState = getStateAfter(event);
        mState = min(mState, newState);
        // 看到這,沒啥好說的了吧?
        mLifecycleObserver.onStateChanged(owner, event);
        mState = newState;
    }
}
複製程式碼

可以看到,這部分會很直白的呼叫到註解生成class中的onStateChanged(),完成生命週期的感知。

3.2、getLifecycle()

getLifecycle()的方式,同樣是返回了一個LifecycleRegistry。因此,最開始我認為系統因此在對應的生命週期完成對上3.1一樣的呼叫。不過看把發現自己還是太年輕。

SupportActivity中,的onCreate方法中,我們可以看到這樣的呼叫:

protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ReportFragment.injectIfNeededIn(this);
}
複製程式碼

是不是感覺到一絲絲熟悉?使用Fragment做生命週期分離管理在很多框架中都出現。接下來我們就好好看看這個ReportFragment

@Override
public void onResume() {
    super.onResume();
    dispatchResume(mProcessListener);
    dispatch(Lifecycle.Event.ON_RESUME);
}

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);
        }
    }
}
複製程式碼

到此就重新回撥到了LifecycleRegistry中的方法了。

尾聲

當然僅憑這些,對於我們來說還遠遠不夠,因此Google還拿出了ViewModelLiveData等相輔相成的有趣模組。下邊的文章將走進:ViewModel篇。

許久沒有寫文章了,一來是最近的確很忙;二來自己也剛開始搞JetPack這一套。學的過程中漸漸發現JatPack屬實比較有意思。所以決定好好的把JetPack研究一翻。

這篇文章就算是自己迴歸寫文章的先導篇吧~

我是一個應屆生,最近和朋友們維護了一個公眾號,內容是我們在從應屆生過渡到開發這一路所踩過的坑,以及我們一步步學習的記錄,如果感興趣的朋友可以關注一下,一同加油~

個人公眾號:IT面試填坑小分隊

相關文章