Jetpack-Lifecycle

Lifecycle介紹

相關(guān)類和接口

使用

實(shí)現(xiàn)原理

Lifecycle-生命周期感知組件

LifecycleJetpack中提供的一個(gè)用于感知生命周期的組件,在應(yīng)用中主要用于監(jiān)聽 ActivityFragment的生命周期變化型型,在合適的時(shí)候釋放資源庵芭,防止內(nèi)存泄露。使用Lifecycle可以將依賴組件的代碼從生命周期方法移入組件本身中涯曲。避免了直接在ActivityFragment的生命周期方法中操作組件野哭。比如,我們常用的方式如下:

class MyActivity:AppCompatActivity() {
    override fun onStart() {
        super.onStart()
        LocationUtils.start()
    }

    override fun onStop() {
        super.onStop()
        LocationUtils.stop()
    }
}

如果多個(gè)頁面都用到了這個(gè)工具類幻件,就需要寫多遍拨黔,如果多人開發(fā),并不能保證一定都會(huì)調(diào)用對應(yīng)的方法绰沥。這樣難以維護(hù)篱蝇。

androidx.lifecycle軟件包提供了可用于構(gòu)建生命周期感知組件的類和接口,這些組件可以根據(jù)ActivityFragment的當(dāng)前生命周期狀態(tài)自動(dòng)調(diào)整其行為徽曲。

相關(guān)類和接口

Lifecycle

Lifecycle本身是一個(gè)抽象類旱易,用于存儲(chǔ)有關(guān)組件(如 ActivityFragment)的生命周期狀態(tài)的信息,并允許其他對象觀察此狀態(tài)管呵。它主要通過兩個(gè)枚舉類:Event和State來關(guān)聯(lián)組件的生命周期淮蜈。

LifecycleOwner

LifecycleOwner是一個(gè)接口,用于返回一個(gè)Lifecycle對象奥此,表示生命周期擁有者弧哎,提供者,屬于被觀察的對象稚虎。

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

LifecycleObserver

LifecycleObserver是一個(gè)標(biāo)記接口撤嫩,任何類都可以通過實(shí)現(xiàn)該接口來感知組件生命周期的變化,屬于觀察對象蠢终。

public interface LifecycleObserver {
}

實(shí)現(xiàn)LifecycleObserver的組件可與實(shí)現(xiàn)LifecycleOwner的組件無縫協(xié)同工作序攘,因?yàn)樯芷谒姓呖梢?strong>提供生命周期鸭限,而觀察者可以注冊以觀察生命周期。

應(yīng)用

Activity和Fragment

在應(yīng)用中两踏,我們常用的就是監(jiān)聽ActivityFragment的生命周期败京。Support Library 26.1.0及更高版本或AndroidX中FragmentActivity已實(shí)現(xiàn)了LifecycleOwner接口。我們只需要將我們的工具類實(shí)現(xiàn)接口LifecycleObserver來檢測或者感知ActivityFragment的生命周期即可梦染。

  • 1.通過向?qū)?yīng)的方法添加注解來監(jiān)控組件的生命周期狀態(tài)赡麦。
  • 2.通過調(diào)用LifecycleaddObserver()方法來添加觀察者
class LocationUtils(lifecycle: Lifecycle) : LifecycleObserver {

    init {
        //添加觀察者
        lifecycle.addObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun start() {
        TODO()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun stop() {
        TODO()
    }
}

//使用,創(chuàng)建對象后帕识,在需要使用的地方直接調(diào)用對應(yīng)的功能即可泛粹,不需要再外面關(guān)聯(lián)組件的生命周期。
val location = LocationUtils(lifecycle)

如果我們需要從另一個(gè)ActivityFragment使用LocationUtils肮疗,只需對其進(jìn)行初始化晶姊。所有設(shè)置和拆解操作都由類本身管理。 這樣還有一個(gè)好處就是:如果start()改成在onResume()中調(diào)用伪货,不需要更改調(diào)用的地方们衙,只需要更改定義的地方。這樣維護(hù)成本低碱呼。

自定義 LifecycleOwner

如果想把我們自定義的類變成為LifecycleOwner蒙挑,就需要借助LifecycleRegistry將事件轉(zhuǎn)發(fā)到該類,如下代碼所示:

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        lifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}

使用生命周期感知組件可以很方便地管理生命周期:

  • 在粗粒度和細(xì)粒度位置更新之間切換愚臀。
  • 停止和開始視頻緩沖忆蚀。
  • 開始和停止網(wǎng)絡(luò)連接。
    暫停和恢復(fù)動(dòng)畫姑裂。

如果Lifecycle的實(shí)現(xiàn)是AppCompatActivityFragment馋袜,那么當(dāng)調(diào)用它們的onSaveInstanceState()方法時(shí),Lifecycle的狀態(tài)會(huì)更改為CREATED并且會(huì)分派ON_STOP事件舶斧。

實(shí)現(xiàn)原理

簡單來說:就是通過一個(gè)無頁面的Fragment欣鳖。通過在對指定Activity注冊無頁面的Fragment,傳遞頁面Activity生命周期Fragment捧毛。然后通過Fragment綁定LifecycleRegistry观堂,當(dāng)Fragment的生命周期變化時(shí)让网,回調(diào)LifecycleRegistryLifecycleObserver對象相應(yīng)的生命周期回調(diào)方法呀忧。

我們觀察Activity的生命周期,只要是通過下述代碼:

 lifecycle.addObserver(this)

就以此為入口溃睹,看一下它的實(shí)現(xiàn):getLifecycle()方法返回的是ComponentActivity中的mLifecycleRegistry而账,如果你用的是support包,它定義SupportActivity中因篇,我這里使用的AndroidX泞辐。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements ...{
    ...
    private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
    ...
    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
    ...
}

我們調(diào)用的addObserver()方法笔横,實(shí)際上調(diào)用的就是LifecycleRegistry里面的:

 public class LifecycleRegistry extends Lifecycle {
    ...
    @Override
    public void addObserver(@NonNull LifecycleObserver observer) {
        State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
        //將傳進(jìn)來的observer包裝成一個(gè)ObserverWithState,并放入集合中
        ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
        ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
        ...
        boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
        State targetState = calculateTargetState(observer);
        mAddingObserverCounter++;
        while ((statefulObserver.mState.compareTo(targetState) < 0
                && mObserverMap.contains(observer))) {
            pushParentState(statefulObserver.mState);
            //分發(fā)事件
            statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
            popParentState();
            targetState = calculateTargetState(observer);
        }
    ...
    }
    ...
}

從上面可以看出有一個(gè)while循環(huán)咐吼,條件是比較觀察者被觀察者State的序數(shù)吹缔, DESTROYED、INITIALIZED锯茄、CREATED厢塘、STARTED和RESUMED的序數(shù)依次為0,1,2,3,4。狀態(tài)變化后肌幽,在該循環(huán)體中晚碾,調(diào)用了statefulObserver.dispatchEvent()方法,分發(fā)事件喂急。該方法的具體實(shí)現(xiàn)如下:

static class ObserverWithState {
    State mState;
    LifecycleEventObserver mLifecycleObserver;

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

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

ObserverWithState創(chuàng)建的時(shí)候?qū)魅氲?code>observer解析并返回接口LifecycleEventObserver實(shí)現(xiàn)類的對象格嘁,最后調(diào)用它的onStateChanged()方法。我們在使用Lifecycle的時(shí)候使用的是注解的方式:@onLifecycleEvent廊移,那么注解處理器會(huì)將該注解解析并動(dòng)態(tài)生成GeneratedAdapte代碼糕簿,這個(gè)GeneratedAdapter會(huì)把對應(yīng)的Lifecycle.Event封裝為方法調(diào)用。最終通過GenericLifecycleObserveonStateChanged方法調(diào)用生成的GeneratedAdaptercallMechods()方法進(jìn)行事件分發(fā)狡孔。

public class LocationUtils_LifecycleAdapter implements GeneratedAdapter {
    final LocationUtils mReceiver;

    LocationUtils_LifecycleAdapter(LocationUtils receiver) {
        this.mReceiver = receiver;
    }

    @Override
    public void callMethods(LifecycleOwner owner, Lifecycle.Event event, boolean onAny,MethodCallsLogger logger) {
        boolean hasLogger = logger != null;
        if (onAny) {
            return;
        }
        if (event == Lifecycle.Event.ON_START) {
            if (!hasLogger || logger.approveCall("start", 1)) {
                mReceiver.start();
            }
            return;
        }
        if (event == Lifecycle.Event.ON_STOP) {
            if (!hasLogger || logger.approveCall("stop", 1)) {
                mReceiver.stop();
            }
            return;
        }
    }
}

上面這個(gè)就是狀態(tài)變化時(shí)事件分發(fā)的基本流程冶伞,那么它是如何感知生命周期狀態(tài)變化的呢?我們調(diào)用LifecycleaddObserver()方法步氏,實(shí)際調(diào)用的是ComponentActivitymLifecycleRegistry對象的方法响禽,而我們關(guān)注Activity的生命周期是從onCreate()開始,所以下面看一下ComponentActivityonCreate()方法:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedStateRegistryController.performRestore(savedInstanceState);
    ReportFragment.injectIfNeededIn(this);
    if (mContentLayoutId != 0) {
        setContentView(mContentLayoutId);
    }
}

onCreate()方法中調(diào)用了ReportFragmentinjectIfNeedIn()方法荚醒。這個(gè)方法其實(shí)就是往Activity中添加了一個(gè)Fragment芋类。而Fragment是依附于Activity的,所以Fragment的生命周期會(huì)跟隨Activity的生命周期界阁。既然ReportFragment能感知Activity的生命周期侯繁,那么它是如何改變狀態(tài)的?

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 onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

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

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        mProcessListener = null;
    }

    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);
            }
        }
    }
    ...
}

從上面可以看出泡躯,在ReportFragment對應(yīng)的生命周期方法中會(huì)調(diào)用dispatch()方法贮竟,并傳遞對應(yīng)的事件Lifecycle.Event.XXX,而dispatch()方法中則是調(diào)用了LifecycleRegistryhandleLifecycleEvent()方法。

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

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;
    //狀態(tài)的變化轉(zhuǎn)化為生命周期事件较剃,然后轉(zhuǎn)發(fā)給 LifecycleObserver
    sync();
    mHandlingEvent = false;
}

一圖勝千語咕别,下面用一張圖來總結(jié)大致的流程:


KotlinAndroid

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市写穴,隨后出現(xiàn)的幾起案子惰拱,更是在濱河造成了極大的恐慌,老刑警劉巖啊送,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件偿短,死亡現(xiàn)場離奇詭異欣孤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)昔逗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進(jìn)店門降传,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勾怒,你說我怎么就攤上這事搬瑰。” “怎么了控硼?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵泽论,是天一觀的道長。 經(jīng)常有香客問我卡乾,道長翼悴,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任幔妨,我火速辦了婚禮鹦赎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘误堡。我一直安慰自己古话,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布锁施。 她就那樣靜靜地躺著陪踩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪悉抵。 梳的紋絲不亂的頭發(fā)上肩狂,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天,我揣著相機(jī)與錄音姥饰,去河邊找鬼傻谁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛列粪,可吹牛的內(nèi)容都是我干的审磁。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼岂座,長吁一口氣:“原來是場噩夢啊……” “哼态蒂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起掺逼,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤吃媒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吕喘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赘那,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年氯质,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了募舟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,928評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闻察,死狀恐怖拱礁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辕漂,我是刑警寧澤呢灶,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站钉嘹,受9級特大地震影響鸯乃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜跋涣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一缨睡、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧陈辱,春花似錦奖年、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至利赋,卻和暖如春嗅义,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背隐砸。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工之碗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人季希。 一個(gè)月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓褪那,卻偏偏與公主長得像,于是被迫代替她去往敵國和親式塌。 傳聞我的和親對象是個(gè)殘疾皇子博敬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評論 2 361

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