手撕Jetpack組件之Lifecycle

為什么需要用Lifecycle衬以?

在使用高德地圖的SDK時,我們一般都會這樣做:

public class MainActivity extends AppCompatActivity {

    private TextureMapView mMapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mMapView = new TextureMapView(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
    }
}

因為組件必須感知Activity的生命周期缓苛,所以一般會直接將代碼寫到Activity的生命周期方法中芳撒。若是當需與Activity生命周期強關聯(lián)的組件比較多時,Activity類里面就會變得非常臃腫未桥,難以維護笔刹。

那么,有沒有一種優(yōu)雅的方式來感知Activity的生命周期呢冬耿?希望有一個觀察者能夠觀察到Activity生命周期的變化舌菜,并且還不用直接引用Activity,將業(yè)務邏輯從Activity抽離出來亦镶。有日月,那就是使用Lifecycle。

簡單使用

  1. 添加依賴
implementation 'androidx.lifecycle:lifecycle-runtime:2.3.1'
  1. 創(chuàng)建一個實現(xiàn)抽象觀察者的具體觀察者
public class MyLifecycleObserver implements LifecycleObserver {

    @OnLifecycleEvent(value = Lifecycle.Event.ON_CREATE)
    private void onCreate() {}

    @OnLifecycleEvent(value = Lifecycle.Event.ON_START)
    private void onStart() {}

    @OnLifecycleEvent(value = Lifecycle.Event.ON_RESUME)
    private void onResume() {}
}
  1. 將被觀察者與觀察者進行關聯(lián)
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getLifecycle().addObserver(new MyLifecycleObserver());
    }
}

Lifecycle是如何感知生命周期的缤骨?

通過上面的分析可知爱咬,Lifecycle使用了觀察者設計模式。抽象觀察者是LifecycleObserver绊起,具體觀察者就是我們實現(xiàn)的MyLifecycleObserver精拟。抽象被觀察者是LifecycleOwner,具體被觀察者就是我們的Activity,實現(xiàn)LifecycleOwner的是我們自己的Activity的父類ComponentActivity蜂绎。最后就是連接觀察者和被觀察者的橋梁Lifecycle栅表,它的實現(xiàn)類是LifecycleRegistry

  • ComponentActivity做了什么荡碾?

在啟動我們自己的Activity的onCreate方法之前谨读,先來看看它的父類ComponentActivity執(zhí)行了一些什么操作。

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

從方法名可以看出注入了一個Fragment坛吁,熟悉Glide的朋友肯定知道這個套路了。添加一個透明的Fragment铐尚,用它來感知宿主Activity的生命周期拨脉,然后進行轉發(fā)。

// ReportFragment.java
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();
        // Hopefully, we are the first to make a transaction.
        manager.executePendingTransactions();
    }
}
  • addObserver做了什么宣增?

分析完了父類Activity的onCreate方法做的事情后玫膀,再來看看我們自己的onCreate方法做的事。

getLifecycle().addObserver(new MyLifecycleObserver());

getLifecycle方法獲取的對象是一個Lifecycle爹脾,它的實現(xiàn)類是LifecycleRegistry帖旨。上面說過的ReportFragment就會使用它來將生命周期的變化轉發(fā)給觀察者。

// ComponentActivity.java
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

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

繼續(xù)跟進到LifecycleRegistry的構造方法灵妨,它有一個比較重要的屬性mState解阅,默認值 是INITIALIZEDLifecycle中有兩個枚舉類泌霍,一個描述被觀察者目前生命周期的狀態(tài)货抄,一個是用來發(fā)給觀察者的事件,通知觀察者目前被觀察者所處的生命周期朱转。如下圖:

640.png

繼續(xù)跟進addObserver方法

// LifecycleRegistry.java
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
    ...
    // 這里的mState一開始是等于INITIALIZED的
    State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
    // 注釋1
    ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
    // 注釋2
    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;
    }
    // mAddingObserverCounter初始化值為0蟹地,mHandlingEvent初始值為false,
    // 所以isReentrance為false
    boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
    // 注釋3
    State targetState = calculateTargetState(observer);
    mAddingObserverCounter++;
    // 注釋4
    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
        pushParentState(statefulObserver.mState);
        final Event event = Event.upFrom(statefulObserver.mState);
        if (event == null) {
            throw new IllegalStateException("no event up from " + statefulObserver.mState);
        }
        statefulObserver.dispatchEvent(lifecycleOwner, event);
        popParentState();
        // mState / subling may have been changed recalculate
        targetState = calculateTargetState(observer);
    }
    // 注釋5
    if (!isReentrance) {
        // we do sync only on the top level.
        sync();
    }
    mAddingObserverCounter--;
}

先看注釋1部分

ObserverWithState statefulObserver = new ObserverWithState(observer,initialState);

將我們的觀察者和初始化狀態(tài)包裝成ObserverWithState對象藤为,在其構造方法內怪与,又創(chuàng)建了一個LifecycleEventObserver類型的觀察者對象,它是一個接口缅疟,它繼承自LifecycleObserver分别,在這里返回的實現(xiàn)類是ReflectiveGenericLifecycleObserver

// LifecycleRegistry.java
LifecycleEventObserver mLifecycleObserver;

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

接著看注釋2部分

ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

將我們的觀察者作為key窿吩,包裝對象ObserverWithState作為value茎杂,將其保存到一個Map中,并且在Map中的value還被維護成了一個雙向鏈表纫雁。

繼續(xù)看注釋3部分

// LifecycleRegistry.java
private State calculateTargetState(LifecycleObserver observer) {
    Map.Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);

    State siblingState = previous != null ? previous.getValue().mState : null;
    State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
            : null;
    return min(min(mState, siblingState), parentState);
}

static State min(@NonNull State state1, @Nullable State state2) {
    return state2 != null && state2.compareTo(state1) < 0 ? state2 : state1;
}

計算我們的觀察者對象的State煌往。這里的previous為包含我們的觀察者對象的Entry節(jié)點的前驅節(jié)點,它不為空且它的StateINITIALIZEDmParentStates的size為空刽脖,所以在return語句中內層min方法返回的是INITIALIZED羞海,而外層min方法返回還是INITIALIZED

繼續(xù)看注釋4部分

    while ((statefulObserver.mState.compareTo(targetState) < 0
            && mObserverMap.contains(observer))) {
        ...
    }

我們的觀察者對象的mState以及由上面calculateTargetState方法返回回來的targetState相等曲管,所以不會進入while循環(huán)却邓。

繼續(xù)看注釋5部分

// LifecycleRegistry.java
if (!isReentrance) {
    // we do sync only on the top level.
    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;
}

private boolean isSynced() {
    if (mObserverMap.size() == 0) {
        return true;
    }
    State eldestObserverState = mObserverMap.eldest().getValue().mState;
    State newestObserverState = mObserverMap.newest().getValue().mState;
    return eldestObserverState == newestObserverState && mState == newestObserverState;
}

在標記處為注釋3的地方的上一句分析了isReentrance為false,所以進入到sync方法院水。先看看進入while循環(huán)的條件判斷方法isSynced腊徙。mObserverMap.eldest()為雙向鏈表的頭節(jié)點,它的mStateINITIALIZED檬某;mObserverMap.newest()為雙向鏈表的尾節(jié)點撬腾,也就是我們的觀察地者對象,它的mState也是為INITIALIZED恢恼。而LifecycleRegistrymSate初始值也是INITIALIZED民傻,所以整個方法返回值為true,while循環(huán)體不會執(zhí)行。

到這里场斑,我們的Activity的onCreate方法分析完成漓踢。接下來就是執(zhí)行前面提到的ReportFragment的生命周期了。我們還是以onCreate方法分例來分析漏隐。

ReportFragment生命周期事件轉發(fā)

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // mProcessListener為空喧半,
    dispatchCreate(mProcessListener);
    dispatch(Lifecycle.Event.ON_CREATE);
}

private void dispatch(@NonNull Lifecycle.Event event) {
    if (Build.VERSION.SDK_INT < 29) {
        // Only dispatch events from ReportFragment on API levels prior
        // to API 29. On API 29+, this is handled by the ActivityLifecycleCallbacks
        // added in ReportFragment.injectIfNeededIn
        dispatch(getActivity(), event);
    }
}

static void dispatch(@NonNull Activity activity, @NonNull Lifecycle.Event event) {
    ...
    if (activity instanceof LifecycleOwner) {
        Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
        if (lifecycle instanceof LifecycleRegistry) {
            ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
        }
    }
}

在一個參數(shù)的dispatch方法中,SDK小于29的才會通過ReportFragment轉發(fā)生命周期事件锁保,那大于等于29的呢薯酝?是通過注冊LifeActivityLifecycleCallbacks來監(jiān)聽Activity的生命周期∷猓可以在ReportFragment#injectIfNeededIn方法查看吴菠。最終生命周期事件轉發(fā)調用到了LifecycleRegistry#handleLifecycleEvent方法。

public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
    enforceMainThreadIfNeeded("handleLifecycleEvent");
    moveToState(event.getTargetState());
}

handleLifecycleEvent方法內先獲取當前event對應的的state浩村,傳過來的eventLifecycle.Event.ON_CREATE做葵,那么對應的stateState.CREATED

@NonNull
public State getTargetState() {
    switch (this) {
        case ON_CREATE:
        case ON_STOP:
            return State.CREATED;
        case ON_START:
        case ON_PAUSE:
            return State.STARTED;
        case ON_RESUME:
            return State.RESUMED;
        case ON_DESTROY:
            return State.DESTROYED;
        case ON_ANY:
            break;
    }
    throw new IllegalArgumentException(this + " has no target state");
}

再回到moveToState方法

private void moveToState(State next) {
// LifecycleRegistry中的mState初始值為INITIALIZED, 而next為CREATED
    if (mState == next) {
        return;
    }
    // 更新mState的值為CREATED
    mState = next;
    if (mHandlingEvent || mAddingObserverCounter != 0) {
        mNewEventOccurred = true;
        // we will figure out what to do on upper level.
        return;
    }
    mHandlingEvent = true;
    // 又回到了我們上面分析過的sync方法心墅。只不過這次會進入這個方法內的while循環(huán)
    sync();
    mHandlingEvent = false;
}

再次回顧sync方法

private void sync() {
    ...
    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;
}

mStateCREATED酿矢,而mObserverMap.eldest()為雙向鏈表的表表頭,state值為INITIALIZED, 所以第一個if條件不會進入怎燥。newest就是包含我們觀察者的節(jié)點瘫筐,此時newestmStage還是INITIALIZED,所以會進入forwardPass方法铐姚。

private void forwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
            mObserverMap.iteratorWithAdditions();
    while (ascendingIterator.hasNext() && !mNewEventOccurred) {
        Map.Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
        // 還記得在注釋1提到的ObserverWithState嗎策肝?
        ObserverWithState observer = entry.getValue();
        while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            pushParentState(observer.mState);
            final Event event = Event.upFrom(observer.mState);
            if (event == null) {
                throw new IllegalStateException("no event up from " + observer.mState);
            }
            observer.dispatchEvent(lifecycleOwner, event);
            popParentState();
        }
    }
}

在注釋1處肛捍,我們的觀察者對象以及mState被包裝成了ObserverWithState對象,繼續(xù)查看其dispatchEvent方法之众。

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

這個mLifecycleObserver是指哪個對象呢拙毫?還是在注釋1處,在創(chuàng)建ObserverWithState對象的構造方法內有對這個值進行賦值棺禾,它的類型就是ReflectiveGenericLifecycleObserver缀蹄。

// ReflectiveGenericLifecycleObserver.java
@Override
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Event event) {
    mInfo.invokeCallbacks(source, event, mWrapped);
}

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

private static void invokeMethodsForEvent(List<MethodReference> handlers,
        LifecycleOwner source, Lifecycle.Event event, Object mWrapped) {
    if (handlers != null) {
        for (int i = handlers.size() - 1; i >= 0; i--) {
            handlers.get(i).invokeCallback(source, event, mWrapped);
        }
    }
}

void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
    //noinspection TryWithIdenticalCatches
    try {
        switch (mCallType) {
            case CALL_TYPE_NO_ARG:
                mMethod.invoke(target);
                break;
            case CALL_TYPE_PROVIDER:
                mMethod.invoke(target, source);
                break;
            case CALL_TYPE_PROVIDER_WITH_EVENT:
                mMethod.invoke(target, source, event);
                break;
        }
    } catch (InvocationTargetException e) {
        throw new RuntimeException("Failed to call observer method", e.getCause());
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

最后通過反射,調用了我們的觀察者實現(xiàn)類MyLifecycleObserver帶有OnLifecycleEvent注解的方法膘婶。

到這里Activity的生命周期onCreate轉發(fā)就已經(jīng)結束缺前。同理,onStart悬襟、onResume等方法的事件分發(fā)差不多都一樣诡延。最后附上一張涉及到相關類的UML圖。

Lifecycle.jpg
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末古胆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子筛璧,更是在濱河造成了極大的恐慌逸绎,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夭谤,死亡現(xiàn)場離奇詭異棺牧,居然都是意外死亡,警方通過查閱死者的電腦和手機朗儒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門颊乘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人醉锄,你說我怎么就攤上這事乏悄。” “怎么了恳不?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵檩小,是天一觀的道長。 經(jīng)常有香客問我烟勋,道長规求,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任卵惦,我火速辦了婚禮阻肿,結果婚禮上,老公的妹妹穿的比我還像新娘沮尿。我一直安慰自己丛塌,他們只是感情好,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著姨伤,像睡著了一般哨坪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乍楚,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天当编,我揣著相機與錄音,去河邊找鬼徒溪。 笑死忿偷,一個胖子當著我的面吹牛,可吹牛的內容都是我干的臊泌。 我是一名探鬼主播鲤桥,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼渠概!你這毒婦竟也來了茶凳?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤播揪,失蹤者是張志新(化名)和其女友劉穎贮喧,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猪狈,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡箱沦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了雇庙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谓形。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖疆前,靈堂內的尸體忽然破棺而出寒跳,到底是詐尸還是另有隱情,我是刑警寧澤峡继,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布冯袍,位于F島的核電站,受9級特大地震影響碾牌,放射性物質發(fā)生泄漏康愤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一舶吗、第九天 我趴在偏房一處隱蔽的房頂上張望征冷。 院中可真熱鬧,春花似錦誓琼、人聲如沸检激。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叔收。三九已至齿穗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饺律,已是汗流浹背窃页。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留复濒,地道東北人脖卖。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像巧颈,于是被迫代替她去往敵國和親畦木。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內容