jetpack系列再看lifecycle實(shí)現(xiàn)原理細(xì)節(jié)

在21年時候有寫過一次lifecycle: http://www.reibang.com/p/838631cdf520骂际。時隔兩三年了剛好最近在看jetpack相關(guān)的一些庫谍椅。回顧下lifecycle實(shí)現(xiàn)源碼. 現(xiàn)在再來看感受又不一樣凳厢,之前可能注重他的流程◎蛎現(xiàn)在更多關(guān)注他的實(shí)現(xiàn)細(xì)節(jié)和為什么這么設(shè)計(jì)碎罚,這樣設(shè)計(jì)的好處是什么欣硼,可能多些自己的思考吧混卵。

1.總體的流程

lifecycle 整個實(shí)現(xiàn)基于觀察者模式映穗,比如我們activity就是被觀察者,我們自己定義一個觀察者 通過addObserver方法 傳入觀察者幕随,把觀察者對象保存在緩存Map中蚁滋,而在componentActivty中 關(guān)聯(lián)了Actiivty生命周期(29以上Activity LifecycleCallbacks生命周期回調(diào)或者空fragment實(shí)現(xiàn)。 內(nèi)部維護(hù)了5個狀態(tài)和6個事件赘淮,來保證觀察者 被觀察者的狀態(tài)一致辕录,如果不一致會觸發(fā)執(zhí)行sync方法從當(dāng)前被觀察者的狀態(tài)獲取事件,觀察者分發(fā)調(diào)用事件梢卸,觸發(fā)onstateChange方法反射調(diào)用觀察者不同的注解生命周期方法走诞。

2.源碼實(shí)現(xiàn)

大部分源碼在上一篇已經(jīng)有了,這里主要補(bǔ)充一下新版本特性和一些細(xì)節(jié)

2.1.被觀察者

Lifecycle是一個接口低剔,里面定義了addObsever()速梗、removeObserver肮塞、兩個枚舉State、Event以及根據(jù)Event獲取State姻锁、根據(jù)State獲取Event的方法 整個框架要用的都定義在里面枕赵。實(shí)現(xiàn)類是LifecycleRegistry

1.androidx的默認(rèn)Activity繼承了ComponentActivity,而ComponentActivity實(shí)現(xiàn)了LifeCycleOwner接口

public class ComponentActivity extends Activity implements
        LifecycleOwner,

LifecycleOwner接口里面只提供了getLifecycle方法

public interface LifecycleOwner {
    @NonNull
    Lifecycle getLifecycle();
}

也正是因?yàn)樘峁┝诉@個方法,他的實(shí)現(xiàn)類可以直接調(diào)用這個方法位隶,看componentActivity的實(shí)現(xiàn)是:

private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
return mLifecycleRegistry;

Fragment 類似的也實(shí)現(xiàn)了LifecycleOwner接口:

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner, SavedStateRegistryOwner {

完成基本介紹后 我們直接看重點(diǎn)ComponentActivity中的onCreate方法:

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
    }

ReportFragment目的就是參考Glide框架添加一個沒有UI的fragment到activity上拷窜,通過FragmentManager關(guān)聯(lián),在Activity源碼中也能看到生命周期變化會調(diào)用FragmentController去dispatch對應(yīng)fragment生命周期函數(shù).

看到添加方法實(shí)現(xiàn)如下涧黄,判斷版本是否大于29:

 public static void injectIfNeededIn(Activity activity) {
        if (Build.VERSION.SDK_INT >= 29) {
            // On API 29+, we can register for the correct Lifecycle callbacks directly
            LifecycleCallbacks.registerIn(activity);
        }
        // Prior to API 29 and to maintain compatibility with older versions of
        // ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and
        // need to support activities that don't extend from FragmentActivity from support lib),
        // use a framework fragment to get the correct timing of Lifecycle events
        android.app.FragmentManager manager = activity.getFragmentManager();
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            // Hopefully, we are the first to make a transaction.
            manager.executePendingTransactions();
        }
    }

根據(jù)版本判斷api29以上注冊ActivityLifecycleCallbacks回調(diào)監(jiān)聽生命周期篮昧,以下的版本添加fragment關(guān)聯(lián)生命周期。主要為了兼容高低版本生命周期變化笋妥。
`
最終都會調(diào)用 dispatch(activity, Lifecycle.Event.ON_XXX)懊昨;區(qū)別是29以上在回調(diào)里面調(diào)用,29以下是在ReportFragment生命周期方法中調(diào)用

    static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
        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)用handleLifecycleEvent 里面又調(diào)用

private void moveToState(State next) {
        if (mState == next) {
            return;
        }
        mState = next;
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        sync();
        mHandlingEvent = false;
    }

這里需要注意的是第一個mState == next 判斷春宣,也就是觀察者lifecycle的狀態(tài)和被觀察者activit的狀態(tài)如果是一樣的酵颁,直接不執(zhí)行后續(xù)邏輯,也就不會觸發(fā)觀察者的生命周期方法月帝,
主要還是保證觀察者被觀察者狀態(tài)一致躏惋,如果不一致則對mstate賦值,再調(diào)用sync方法

 private void sync() {
        LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
        if (lifecycleOwner == null) {
            throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
                    + "garbage collected. It is too late to change lifecycle state.");
        }
        while (!isSynced()) {
            mNewEventOccurred = false;
            // no need to check eldest for nullability, because isSynced does it for us.
            if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
                backwardPass(lifecycleOwner);
            }
            Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass(lifecycleOwner);
            }
        }
        mNewEventOccurred = false;
    }

里面代碼也比較清晰嚷辅,如果觀察者被觀察者狀態(tài)不一致一致執(zhí)行循環(huán)保證一致簿姨,不一致則比較誰的狀態(tài)值大,分別狀態(tài)遷移 后移簸搞。

 Event event = Event.downFrom(observer.mState);
                if (event == null) {
                    throw new IllegalStateException("no event down from " + observer.mState);
                }
                pushParentState(event.getTargetState());
                observer.dispatchEvent(lifecycleOwner, event);

里面其實(shí)是根據(jù)當(dāng)前的狀態(tài)扁位,取出事件類型再調(diào)用observer的分發(fā)事件 來保持狀態(tài)一致。而分發(fā)事件攘乒,核心代碼是下面的:

  mLifecycleObserver.onStateChanged(owner, event);

onStateChanged接口方法的實(shí)現(xiàn)是初始化時候addObsever()時候保存的觀察者信息類到
ReflectiveGenericLifecycleObserver

 void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) {
            invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target);
            invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event,
                    target);
        }

里面用到線程安全的map,key是觀察者贤牛,value是包裝后的對象里面保存了觀察者和初始狀態(tài)
再通過反射調(diào)用觀察者的對應(yīng)注解的方法

3.思考和總結(jié)

1.為什么涉及mActive變量?
格局出發(fā)则酝,mActive設(shè)計(jì)不知給自己用殉簸,還為了給別的框架用。lifecycle雖然是一個組件沽讹,更多的是他結(jié)合liveData viewModle等一起用般卑,比如liveData在mActive為onStart、onResume才執(zhí)行一些邏輯 否則直接過濾爽雄,保證了一些場景安全蝠检,頁面都關(guān)了網(wǎng)絡(luò)請求回來刷新數(shù)據(jù)。
2.為什么要把狀態(tài)涉及為復(fù)用的挚瘟?
個人猜測是為了減少狀態(tài)的值少兩個叹谁,同時區(qū)分開Activity的本身狀態(tài)饲梭。如果定義了和Activit生命周期一樣的狀態(tài),感覺會比較重復(fù)焰檩,但是又為了記錄當(dāng)前狀態(tài)憔涉。

3.里面設(shè)計(jì)思想?設(shè)計(jì)模式析苫?
源碼里面真的是大量使用設(shè)計(jì)模式兜叨,這里用到觀察者模式、建造者模式衩侥、享元国旷、裝飾、模版方法茫死、工廠跪但、單例很多都涉及到了。不一一舉例峦萎。

4.ReportFragment的injectIfNeededIn方法為什么要區(qū)分29以上版本
API 29 或以上版本進(jìn)行區(qū)分的原因主要在于 Android 對 Fragment 的管理和生命周期有所變化
以前的版本中特漩,ReportFragment 需要用老的 android.app.Fragment 來保證與老的 lifecycle-runtime 的兼容性。
從 API 29 開始骨杂,Android 引入了新的 Fragment API(androidx.fragment.app.Fragment),并且對 Fragment 生命周期進(jìn)行了優(yōu)化雄卷,當(dāng) Activity 調(diào)用 onStop 時搓蚪,F(xiàn)ragment 的 onStop 會先于 Activity 的 onStop 被調(diào)用,這樣就可以在 Fragment 中更早地保存狀態(tài)丁鹉。而在 API 29 之前妒潭,F(xiàn)ragment 的 onStop 是在 Activity 的 onStop 之后調(diào)用的。
5.使用場景如何揣钦,用起來是否方便
一般結(jié)合LiveData viewModle使用雳灾,上家公司也直接結(jié)合MVP模式管理生命周期防止業(yè)務(wù)開發(fā)同學(xué)忘記手動釋放資源。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末冯凹,一起剝皮案震驚了整個濱河市谎亩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宇姚,老刑警劉巖匈庭,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浑劳,居然都是意外死亡阱持,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門魔熏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衷咽,“玉大人鸽扁,你說我怎么就攤上這事∠馄” “怎么了桶现?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長卖词。 經(jīng)常有香客問我巩那,道長,這世上最難降的妖魔是什么此蜈? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任即横,我火速辦了婚禮,結(jié)果婚禮上裆赵,老公的妹妹穿的比我還像新娘东囚。我一直安慰自己,他們只是感情好战授,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布页藻。 她就那樣靜靜地躺著,像睡著了一般植兰。 火紅的嫁衣襯著肌膚如雪份帐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天楣导,我揣著相機(jī)與錄音废境,去河邊找鬼。 笑死筒繁,一個胖子當(dāng)著我的面吹牛噩凹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毡咏,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼驮宴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了呕缭?” 一聲冷哼從身側(cè)響起堵泽,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恢总,沒想到半個月后落恼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡离熏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年佳谦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滋戳。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡钻蔑,死狀恐怖啥刻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咪笑,我是刑警寧澤可帽,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站窗怒,受9級特大地震影響映跟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扬虚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一努隙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辜昵,春花似錦荸镊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至舀锨,卻和暖如春岭洲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坎匿。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工钦椭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碑诉。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像侥锦,于是被迫代替她去往敵國和親进栽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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