【AAC 系列二】深入理解架構組件的基石:Lifecycle

0. 前言

在前文,我就提到 Android Architecture Components (后簡稱為 AAC),是一個幫助開發者設計 健壯可測試可維護 的一系列庫的集合。

Lifecycle 就是 AAC 中的一員,它能夠幫助我們方便的管理 Activity 以及 Fragment 的生命周期

本文帶大家深入了解 Lifecycle 。

注意:本文基于 Lifecycle 1.1.1 版本,Android API 26 ,依賴如下圖。<br /><br />

image.png
image.png
<br /><br /><br />并假設讀者對 Lifecycle 有基本的了解,我繪制了一個基本的類圖,如果對于下面類圖所涉及到的類都還算了解則可以繼續閱讀下去,如果完全不知道,建議閱讀一些教程先。<br /><br />
image.png
image.png

<a name="e2000022"></a>

1. Lifecycle 使用基礎

在 AppCompatActivity 里我們可以通過 getLifecycle() 方法拿到 Lifecycle ,并添加 Observer 來實現對 Activity 生命周期的監聽。

一個簡單的使用例子如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testLifecycle();
    }

    private void testLifecycle() {
        getLifecycle().addObserver(new LifecycleObserver() {

            @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
            void onResume(){
                Log.d(TAG, "LifecycleObserver onResume() called");
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
    }
}

啟動 MainActivity 就可以看到如下日志:

D/MainActivity: onResume: 
D/MainActivity: LifecycleObserver onResume() called

日志說明我們通過上述代碼確實實現了監聽生命周期的功能。

那么問題來了,這是怎么做到的?

我把這個問題拆分成了兩塊:

  1. 生命周期的感知問題是什么感知了Activity的生命周期
  2. 注解方法的調用問題是什么調用了我們使用注解修飾的方法

<a name="7f514a69"></a>

2. 感知生命周期的原理

<a name="610796fd"></a>

2.1 初現端倪 ReportFragment

我通過調試堆棧發現了一個叫做 ReportFragment 的類,非常可疑,遂跟蹤之。

注意:Debug 查看堆棧是閱讀源碼手段中最常用最簡單最好用最親民的方法,沒有之一,每個人都應該熟練掌握。

來看看這個類都寫了什么:

public class ReportFragment extends Fragment {

    private static final String REPORT_FRAGMENT_TAG = "android.arch.lifecycle"
            + ".LifecycleDispatcher.report_fragment_tag";
        //注入 Fragment 的方法
    public static void injectIfNeededIn(Activity activity) {
        // ProcessLifecycleOwner should always correctly work and some activities may not extend
        // FragmentActivity from support lib, so we use framework fragments for activities
        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();
        }
    }
    //...
    @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);
        // just want to be sure that we won't leak reference to an activity
        mProcessListener = null;
    }
        //分發生命周期事件給 LifecycleRegistryOwner 的 Lifecycle 或者 LifecycleRegistry
    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 在發揮作用,Lifecycle 利用了 Fragment 來實現監聽生命周期,并在生命周期回調里調用了內部 dispatch 的方法來分發生命周期事件。(怎么分發后面講)

<a name="4bc29167"></a>

2.2 幕后“黑手” SupportActivity

從方法來看注入 Fragment 的方法應該是調用 injectIfNeededIn(Activity) 的地方了。

在通過搜索 發現 SupportActivity 調用了該方法。(API 28 的版本是 ComponentActivity ,代碼實現沒什么差別)

public class SupportActivity extends Activity implements LifecycleOwner, Component {

    //擁有一個 LifecycleRegistry
    private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在 onCreate 里注入了 ReportFragment
        ReportFragment.injectIfNeededIn(this);
    }

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

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

可以看到 SupportActivity 內部包含了一個 LifecycleRegistry ,并實現了 LifecycleOwner , 并且在 onCreate 方法里 調用了 ReportFragment.injectIfNeededIn(this); 注入ReportFragment

LifecycleRegistry 是 Lifecycle 的實現,并負責管理 Observer ,在上面【2】章節的 dispatch 方法中已經看到了該類的出現,它的 handleLifecycEvent 接受了生命周期的回調。

<a name="dceb7b2f"></a>

2.3 Lifecycle 的生命周期事件與狀態的定義

這小節補充一下 Lifecycle 的回調與 Activity 、Fragment 的生命周期對標相關知識,后面分析會出現。

Lifecycle 中定義了 Event : 表示生命周期事件, State : 表示當前狀態。

<a name="dc278a7c"></a>

2.3.1 Lifecycle.Event

Lifecycle 定義的生命周期事件,與 Activity 生命周期類似。

    public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }

<a name="de88adb7"></a>

2.3.2 Lifecycle.State

State 表示當前組件的生命周期狀態。

    /**
        * Lifecycle states. You can consider the states as the nodes in a graph and
        * {@link Event}s as the edges between these nodes.
        */
        public enum State {
        DESTROYED,
        INITIALIZED,
        CREATED,
        STARTED,
        RESUMED;
        public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }
    }

<a name="48978dd0"></a>

2.3.3 Event 與 State 的關系:
image.png
image.png

(圖1.圖來源見【8.2】)

<a name="cc12ac66"></a>

2.4 小結

通過研究我們發現,SupportActivity 在 onCreate 方法里注入了 ReportFragment ,通過 Fragment 的機制來實現生命周期的監聽

實際上利用 Fragment 監聽 Activity 生命周期的功能在開源社區由來已久, Lifecycle 并非原創,Lifecycle 的出現算是把這個實現官方化了。

相比于第三方的實現,嵌入到 Android 源碼中的實現對開發者來說是非常有好處的,即屏蔽了細節,又降低了使用難度。<br />**
<a name="731a721b"></a>

3. 注解方法被調用的原理

OnLifecycleEvent 注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OnLifecycleEvent {
    Lifecycle.Event value();
}

看到有 RetentionPolicy.RUNTIME 修飾,我就猜測它是靠反射來實現了,不過還是看下具體實現驗證下吧。

之前在了解完生命周期監聽的原理的同時,我們也看到了生命周期事件的接收者 LifecycleRegistry ,是它的 handleLifecycleEvent() 接收了事件,我們繼續追蹤。

    /**
     * Sets the current state and notifies the observers.
     * Note that if the {@code currentState} is the same state as the last call to this method,
     * calling this method has no effect.
     */
    public void handleLifecycleEvent(Lifecycle.Event event) {
        mState = getStateAfter(event);
        if (mHandlingEvent || mAddingObserverCounter != 0) {
            mNewEventOccurred = true;
            // we will figure out what to do on upper level.
            return;
        }
        mHandlingEvent = true;
        sync();
        mHandlingEvent = false;
    }

其實從方法注釋就能看出來了,就是它處理了狀態并通知了 observer 。

看下 getStateAfter() 方法:

   static State getStateAfter(Event event) {
        switch (event) {
            case ON_CREATE:
            case ON_STOP:
                return CREATED;
            case ON_START:
            case ON_PAUSE:
                return STARTED;
            case ON_RESUME:
                return RESUMED;
            case ON_DESTROY:
                return DESTROYED;
            case ON_ANY:
                break;
        }
        throw new IllegalArgumentException("Unexpected event value " + event);
    }

getStateAfter() 這個方法根據當前 Event 獲取對應的 State ,細看其實就是 【2.3.3】中那個圖的代碼實現。

接下去看 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();
            }
            Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
            if (!mNewEventOccurred && newest != null
                    && mState.compareTo(newest.getValue().mState) > 0) {
                forwardPass();
            }
        }
        mNewEventOccurred = false;
    }

sync 方法里對比了當前 mState 以及上一個 State ,看是應該前移還是后退,這個對應了生命周期的前進跟后退,打個比方就是從 onResume -> onPause (forwardPass),onPause -> onResume (backwardPass),拿 backwardPass() 舉例吧。(forwardPass方法處理類似)

    private void backwardPass(LifecycleOwner lifecycleOwner) {
        Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
                mObserverMap.descendingIterator();
        while (descendingIterator.hasNext() && !mNewEventOccurred) {
            Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
            ObserverWithState observer = entry.getValue();
            while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
                    && mObserverMap.contains(entry.getKey()))) {
                //調用 downEvent 獲取更前面的 Event
                Event event = downEvent(observer.mState);
                pushParentState(getStateAfter(event));
                //分發 Event 
                observer.dispatchEvent(lifecycleOwner, event);
                popParentState();
            }
        }
    }
        
    private static Event downEvent(State state) {
        switch (state) {
            case INITIALIZED:
                throw new IllegalArgumentException();
            case CREATED:
                return ON_DESTROY;
            case STARTED:
                return ON_STOP;
            case RESUMED:
                return ON_PAUSE;
            case DESTROYED:
                throw new IllegalArgumentException();
        }
        throw new IllegalArgumentException("Unexpected state value " + state);
    }

通過源碼可以看到, backwardPass() 方法調用 downEvent 獲取往回退的目標 Event。

可能比較抽象,舉個例子,在 onResume 的狀態,我們按了 home,這個時候就是 RESUMED 的狀態變到 STARTED 的狀態,對應的要發送的 Event 是 ON_PAUSE,這個就是 backwardPass() 的邏輯了

如果前面的代碼都是引子的話,我們最終看到了一絲分發的痕跡了—— observer.dispatchEvent(lifecycleOwner, event)

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

可以看到最后調用了 GenericLifecycleObserver.onStateChanged() 方法,再跟。

class ReflectiveGenericLifecycleObserver implements GenericLifecycleObserver {
    //mWrapped 是 我們的 Observer
    private final Object mWrapped;
    //反射 mWrapped 獲取被注解了的方法
    private final CallbackInfo mInfo;
    @SuppressWarnings("WeakerAccess")
    static final Map<Class, CallbackInfo> sInfoCache = new HashMap<>();

    ReflectiveGenericLifecycleObserver(Object wrapped) {
        mWrapped = wrapped;
        mInfo = getInfo(mWrapped.getClass());
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Event event) {
        invokeCallbacks(mInfo, source, event);
    }
    
    private void invokeCallbacks(CallbackInfo info, LifecycleOwner source, Event event) {
        invokeMethodsForEvent(info.mEventToHandlers.get(event), source, event);
        invokeMethodsForEvent(info.mEventToHandlers.get(Event.ON_ANY), source, event);
    }
  
    private void invokeMethodsForEvent(List<MethodReference> handlers, LifecycleOwner source,
            Event event) {
        if (handlers != null) {
            for (int i = handlers.size() - 1; i >= 0; i--) {
                MethodReference reference = handlers.get(i);
                invokeCallback(reference, source, event);
            }
        }
    }
    //最后走到 invokeCallback 這里
    private void invokeCallback(MethodReference reference, LifecycleOwner source, Event event) {
        //noinspection TryWithIdenticalCatches
        try {
            switch (reference.mCallType) {
                case CALL_TYPE_NO_ARG:
                    reference.mMethod.invoke(mWrapped);
                    break;
                case CALL_TYPE_PROVIDER:
                    reference.mMethod.invoke(mWrapped, source);
                    break;
                case CALL_TYPE_PROVIDER_WITH_EVENT:
                    reference.mMethod.invoke(mWrapped, source, event);
                    break;
            }
        } catch (InvocationTargetException e) {
            throw new RuntimeException("Failed to call observer method", e.getCause());
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
    
    private static CallbackInfo getInfo(Class klass) {
        CallbackInfo existing = sInfoCache.get(klass);
        if (existing != null) {
            return existing;
        }
        existing = createInfo(klass);
        return existing;
    }
    
    //通過反射獲取 method 信息
    private static CallbackInfo createInfo(Class klass) {
        //...
        Method[] methods = klass.getDeclaredMethods();

        Class[] interfaces = klass.getInterfaces();
        for (Class intrfc : interfaces) {
            for (Entry<MethodReference, Event> entry : getInfo(intrfc).mHandlerToEvent.entrySet()) {
                verifyAndPutHandler(handlerToEvent, entry.getKey(), entry.getValue(), klass);
            }
        }

        for (Method method : methods) {
            OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
            if (annotation == null) {
                continue;
            }
            Class<?>[] params = method.getParameterTypes();
            int callType = CALL_TYPE_NO_ARG;
            if (params.length > 0) {
                callType = CALL_TYPE_PROVIDER;
                if (!params[0].isAssignableFrom(LifecycleOwner.class)) {
                    throw new IllegalArgumentException(
                            "invalid parameter type. Must be one and instanceof LifecycleOwner");
                }
            }
            Event event = annotation.value();
            //...
            MethodReference methodReference = new MethodReference(callType, method);
            verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
        }
        CallbackInfo info = new CallbackInfo(handlerToEvent);
        sInfoCache.put(klass, info);
        return info;
    }

    @SuppressWarnings("WeakerAccess")
    static class CallbackInfo {
        final Map<Event, List<MethodReference>> mEventToHandlers;
        final Map<MethodReference, Event> mHandlerToEvent;

        CallbackInfo(Map<MethodReference, Event> handlerToEvent) {
            //...
        }
    }

    static class MethodReference {
        final int mCallType;
        final Method mMethod;

        MethodReference(int callType, Method method) {
            mCallType = callType;
            mMethod = method;
            mMethod.setAccessible(true);
        }
    }

    private static final int CALL_TYPE_NO_ARG = 0;
    private static final int CALL_TYPE_PROVIDER = 1;
    private static final int CALL_TYPE_PROVIDER_WITH_EVENT = 2;
}

這個類的代碼比較多,不過也不復雜。可以看到最后代碼走到了invokeCallback() ,通過反射調用了方法。

而這個方法是 createInfo() 方法中反射遍歷我們注冊的 Observer 的方法找到的被 OnLifecycleEvent 注解修飾的方法,并且按 Event 類型存儲到了 info.mEventToHandlers 里。

到這里整個鏈路就清晰了,我們在 Observer 用注解修飾的方法,會被通過反射的方式獲取,并保存下來,然后在生命周期發生改變的時候再找到對應 Event 的方法,通過反射來調用方法

注意:源碼中還有一些細節比較繁瑣,比如怎么獲取的方法,怎么包裝的 Observer ,State 的管理以及存儲等,就不在這里展開了,有興趣的自行了解。

<a name="9d59d5ab"></a>

4. 圖解 Lifecycle

如果被代碼繞暈了,也沒關系,我畫了類圖以及時序圖,幫助大家理解,配合著類圖跟時序圖看代碼,會容易理解很多。

<a name="8870bf02"></a>

4.1 Lifecycle 相關原理類的 UML 圖

核心類 UML 圖整理如下:

Lifecycle-UML.jpg
Lifecycle-UML.jpg

<br />(圖2. Lifecycle-UML圖)

<a name="1e15f81c"></a>

4.1 Lifecycle 原理時序圖

圖中起始于 onCreate ,順便利用 onCreate 描繪整個流程。(其他生命周期原理一樣,不重復畫了)

image.png
image.png

<br />(圖3. Lifecycle 時序圖)<br />

<a name="f4ac431e"></a>

4.3 Lifecycle State 與 Event 的關系圖

圖展示了 State 與 Event 的關系,以及隨著生命周期走向它們發生的變化。

Lifecycle-Seq2.png
Lifecycle-Seq2.png

<br />(圖4. State 與 Event 的關系圖)

<a name="f34f38b9"></a>

5. Lifecycle 的實戰應用

好了,重點的原理我們分析完畢了,如果看一遍沒有理解,就多看幾遍。

這個小節來講講 Lifecycle 的實戰應用。

Lifecycle 的應用場景非常廣泛,我們可以利用 Lifecycle 的機制來幫助我們將一切跟生命周期有關的業務邏輯全都剝離出去,進行完全解耦,比如視頻的暫停與播放,Handler 的消息移除,網絡請求的取消操作,Presenter 的 attach&detach View 等等,并且可以以一個更加優雅的方式實現,還我們一個更加干凈可讀的 Activity & Fragment。

下面舉個簡單的例子:

<a name="9e4c4589"></a>

5.1 自動移除 Handler 的消息:LifecycleHandler

我們擔心 Handler 會導致內存泄露,通常會在 onDestroy 里移除消息,寫多了煩,但是結合 Lifecyc le ,我們可以寫出一個 lifecycle-aware 的 Handler,自動在 onDestroy 里移除消息,不再需要寫那行樣板代碼。

代碼實現如下:

image.png
image.png

該代碼已經包含在我的開源庫 Pandora 里了,可以訪問:https://github.com/AlanCheen/Pandora ,直接依賴使用,歡迎 star。

<a name="95f1f640"></a>

5.2 給 ViewHolder 添加 Lifecycle 的能力

有些 App 會有長列表的頁面,里面塞了各種不用樣式的 Item,通常會用 RecyclerView 來實現,有時候部分 Item 需要獲知生命周期事件,比如包含播放器的 Item 需要感知生命周期來實現暫停/重播的功能,借助 Lifecycle 我們可以實現。

具體實現可以參考我的開源庫 Flap:https://github.com/AlanCheen/Flap

<a name="12eaa1dd"></a>

6. 知識點梳理匯總

  1. **Lifecycle** 庫通過在 SupportActivityonCreate 中注入 ReportFragment 來感知發生命周期;
  2. **Lifecycle** 抽象類,是 Lifecycle 庫的核心類之一,它是對生命周期的抽象,定義了生命周期事件以及狀態,通過它我們可以獲取當前的生命周期狀態,同時它也奠定了觀察者模式的基調;(我是黨員你看出來了嗎:-D)
  3. **LifecycleOwner** ,描述了一個擁有生命周期的組件,可以自己定義,不過通常我們不需要,直接使用 AppCompatActivity 等即可;
  4. **LifecycleRegistry**Lifecycle 的實現類,它負責接管生命周期事件,同時也負責 Observer 的注冊以及通知;
  5. **ObserverWithState** ,是 Observer 的一個封裝類,是它最終 通過 ReflectiveGenericLifecycleObserve 調用了我們用注解修飾的方法;
  6. **LifecycleObserver** ,Lifecycle 的觀察者,利用它我們可以享受 Lifecycle 帶來的能力;
  7. **ReflectiveGenericLifecycleObserver**,它存儲了我們在 Observer 里注解的方法,并在生命周期發生改變的時候最終通過反射的方式調用對應的方法。

<a name="7e4acf90"></a>

7. 總結

Lifecycle 是一個專門用來處理生命周期的庫,它能夠幫助我們將 Acitivity、Framgent 的生命周期處理與業務邏輯處理進行完全解耦,讓我們能夠更加專注于業務;通過解耦讓 Activity、Fragment 的代碼更加可讀可維護。

可以這么說 Lifecycle 的出現徹底解決了 Android 開發遇到的生命周期處理難題,并且還給開發者帶來了新的架構姿勢,讓我們可以設計出更加合理的架構。

媽媽再也不用擔心我遇到生命周期難題了!

同時 Lifecycle 作為 AAC 的基石,為 LiveDataViewModel 的登場打下堅實的基礎。

那么,LiveData、ViewModel 的背后又是什么原理呢?

盡請期待下一篇!

<a name="7ba2d9c6"></a>

8. 參考與推薦

  1. https://developer.android.com/topic/libraries/architecture
  2. https://developer.android.com/topic/libraries/architecture/lifecycle
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容