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

栏目: Android · 发布时间: 5年前

内容简介:你好,我是程序亦非猿,阿里巴巴资深客户端工程师一枚本文是深入理解 AAC 系列的第二篇,第一篇请看这里:在前文,我就提到 Android Architecture Components (后简称为 AAC),是一个帮助开发者设计

你好,我是程序亦非猿,阿里巴巴资深客户端工程师一枚

本文是深入理解 AAC 系列的第二篇,第一篇请看这里: juejin.im/post/5cd4ea…

在前文,我就提到 Android Architecture Components (后简称为 AAC),是一个帮助开发者设计 健壮可测试可维护 的一系列库的集合。

Lifecycle 就是 AAC 中的一员, 它能够帮助我们方便的管理 Activity 以及 Fragment 的生命周期

本文带大家深入了解 Lifecycle 。

注意:本文基于 Lifecycle 1.1.1 版本,Android API 26 ,依赖如下图。

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


并假设读者对 Lifecycle 有基本的了解,我绘制了一个基本的类图,如果对于下面类图所涉及到的类都还算了解则可以继续阅读下去,如果完全不知道,建议阅读一些教程先。

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

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 的关系:

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

(图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 图整理如下:

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

(图2. Lifecycle-UML图)

4.1 Lifecycle 原理时序图

图中起始于 onCreate ,顺便利用 onCreate 描绘整个流程。(其他生命周期原理一样,不重复画了)

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

(图3. Lifecycle 时序图)

4.3 Lifecycle State 与 Event 的关系图

图展示了 State 与 Event 的关系,以及随着生命周期走向它们发生的变化。

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

(图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 里移除消息,不再需要写那行样板代码。

代码实现如下:

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

该代码已经包含在我的开源库 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 的背后又是什么原理呢?

尽请期待下一篇!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

离散数学及其应用(英文版·第5版)

离散数学及其应用(英文版·第5版)

Kenneth H.Rosen / 机械工业出版社 / 2003 / 79.00元

本书第4版是全球500多所大学的指之一教材,获得了极大的成功。中文版也已被国内大学广泛有用为教材。第5版在前四版的基础上做了大量的改进,使其成为更有效的教学工具。   本书可作为1至2个学期的离散数学课入门教材,适用于数学、计算机科学、工程等专业的学生。一起来看看 《离散数学及其应用(英文版·第5版)》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

html转js在线工具
html转js在线工具

html转js在线工具