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

0. 序言

【AAC 系列一】Android 應用架構新時代來臨!java

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

【AAC 系列三】深刻理解架構組件:LiveDataandroid

這個連接不要點,千萬不要git

你好,我是程序亦非猿,阿里巴巴資深客戶端工程師一枚github

本文是深刻理解 AAC 系列的第二篇,第一篇請看這裏:juejin.im/post/5cd4ea…網絡

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

Lifecycle  就是 AAC 中的一員,它可以幫助咱們方便的管理 Activity 以及 Fragment 的生命週期app

本文帶你們深刻了解 Lifecycle 。ide

注意:本文基於 Lifecycle 1.1.1 版本,Android API 26 ,依賴以下圖。

post

image.png



並假設讀者對 Lifecycle 有基本的瞭解,我繪製了一個基本的類圖,若是對於下面類圖所涉及到的類都還算了解則能夠繼續閱讀下去,若是徹底不知道,建議閱讀一些教程先。

image.png

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. 註解方法的調用問題是什麼調用了咱們使用註解修飾的方法 ?

2. 感知生命週期的原理

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  的方法來分發生命週期事件。(怎麼分發後面講)

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  接受了生命週期的回調。

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

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

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

2.3.1 Lifecycle.Event

Lifecycle  定義的生命週期事件,與 Activity 生命週期相似。

public enum Event {
        ON_CREATE,
        ON_START,
        ON_RESUME,
        ON_PAUSE,
        ON_STOP,
        ON_DESTROY,
        ON_ANY
    }
複製代碼

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;
        }
    }
複製代碼

2.3.3 Event 與 State 的關係:

image.png

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

2.4 小結

經過研究咱們發現,SupportActivity 在 onCreate 方法裏注入了 ReportFragment ,經過 Fragment 的機制來實現生命週期的監聽

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

相比於第三方的實現,嵌入到 Android 源碼中的實現對開發者來講是很是有好處的,即屏蔽了細節,又下降了使用難度。
**

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 的管理以及存儲等,就不在這裏展開了,有興趣的自行了解。

4. 圖解 Lifecycle

若是被代碼繞暈了,也不要緊,我畫了類圖以及時序圖,幫助你們理解,配合着類圖跟時序圖看代碼,會容易理解不少。

4.1 Lifecycle 相關原理類的 UML 圖

核心類 UML 圖整理以下:

Lifecycle-UML.jpg

(圖2. Lifecycle-UML圖)

4.1 Lifecycle 原理時序圖

圖中起始於 onCreate ,順便利用 onCreate 描繪整個流程。(其餘生命週期原理同樣,不重複畫了)

image.png

(圖3. Lifecycle 時序圖)

4.3 Lifecycle State 與 Event 的關係圖

圖展現了 State 與 Event 的關係,以及隨着生命週期走向它們發生的變化。

Lifecycle-Seq2.png

(圖4. State 與 Event 的關係圖)

5. Lifecycle 的實戰應用

好了,重點的原理咱們分析完畢了,若是看一遍沒有理解,就多看幾遍。

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

Lifecycle 的應用場景很是普遍,咱們能夠利用 Lifecycle 的機制來幫助咱們將一切跟生命週期有關的業務邏輯全都剝離出去,進行徹底解耦,好比視頻的暫停與播放,Handler 的消息移除,網絡請求的取消操做,Presenter 的 attach&detach View 等等,而且能夠以一個更加優雅的方式實現,還咱們一個更加乾淨可讀的 Activity & Fragment。

下面舉個簡單的例子:

5.1 自動移除 Handler 的消息:LifecycleHandler

咱們擔憂 Handler 會致使內存泄露,一般會在 onDestroy 裏移除消息,寫多了煩,可是結合 Lifecyc le ,咱們能夠寫出一個 lifecycle-aware 的 Handler,自動在 onDestroy 裏移除消息,再也不須要寫那行樣板代碼。

代碼實現以下:

image.png

該代碼已經包含在個人開源庫 Pandora 裏了,能夠訪問:github.com/AlanCheen/P… ,直接依賴使用,歡迎 star。

5.2 給 ViewHolder 添加 Lifecycle 的能力

有些 App 會有長列表的頁面,裏面塞了各類不用樣式的 Item,一般會用 RecyclerView 來實現,有時候部分 Item 須要獲知生命週期事件,好比包含播放器的 Item 須要感知生命週期來實現暫停/重播的功能,藉助 Lifecycle 咱們能夠實現。

具體實現能夠參考個人開源庫 Flap:github.com/AlanCheen/F… 。

6. 知識點梳理彙總

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

7. 總結

Lifecycle 是一個專門用來處理生命週期的庫,它可以幫助咱們將 Acitivity、Framgent 的生命週期處理與業務邏輯處理進行徹底解耦,讓咱們可以更加專一於業務;經過解耦讓 Activity、Fragment 的代碼更加可讀可維護。

能夠這麼說 Lifecycle 的出現完全解決了 Android 開發遇到的生命週期處理難題,而且還給開發者帶來了新的架構姿式,讓咱們能夠設計出更加合理的架構。

媽媽不再用擔憂我遇到生命週期難題了!

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

那麼,LiveData、ViewModel 的背後又是什麼原理呢?

盡請期待下一篇!

8. 參考與推薦

  1. developer.android.com/topic/libra…
  2. developer.android.com/topic/libra…

公衆號:程序亦非猿
相關文章
相關標籤/搜索