Jetpack管理生命周期——Lifecycle

作者: 谁动了我的代码 | 来源:发表于2023-02-19 16:08 被阅读0次

    Android Jetpack

    对于任何一个产品来说,我们开发中都会面对哪些问题?如:产品交互、用户体验、代码结构、数据获取、数据存储、网络优化、任务调度等等,虽然在现在的阶段这些问题已经有了很好的解决和优化,也有很多大神的开源组件方便开发者去使用,Android Jetpack就是Google给出的一个官方的处理方法(当然知识处理其中基本问题),Android Jetpack组件的优势:

    轻松管理应用程序的生命周期构建可观察的数据对象,以便在基础数据库更改时通知视图存储在应用程序轮换中未销毁的UI相关数据,在界面重建后恢复数据轻松的实现SQLite数据库系统自动调度后台任务的执行,优化使用性能

    Android Jetpack组件推荐的使用项目架构

    image

    上面架构组件的功能如下:

    Activity和Fragment负责产品与用户的交互ViewModel作为数据的存储和驱动Resposity负责调度数据的获取Room储存本地序列化的数据Retrofit获取远程数据的数据

    Jetpack组件 Lifecycle 介绍

    早期的架构中,生命周期的事件监听和状态查询,需要直接在Activity/Fragment的生命周期钩子中处理。而实际开发中,往往需要在Activity/Fragment外部进行事件监听和状态查询。在Lifecycle引入前,需要开发者自定义一套提供侦测功能的Activity/Fragment基类及回调接口。

    Lifecycle的引入,即是对以上需求的官方支持。类似的,在官方推出ViewModels以前,已经存在通过Fragment实现相同功能的方案。

    Lifecycler的原理:

    Lifecycler为每个活动组件添加了一个没有界面的Fragment,利用Fragment周期会根据活动声明周期变化的特性实现的特性,从而实现生命周期的感知,然后根据注解的Event查找执行相应的方法。

    如何管理生命周期

    Lifecycle的出现帮我们解决生命周期管理的问题。这一块对于我们日常开发来说的确是比较坑的一点,生命周期处理不当,很容易造成内存泄漏。 为了能让我们业务代码能够感知到生命周期,我们可能会写大量的代码。比如在让Presenter拥有感知生命周期的能力,我们可能会这么做:

    public interface IPresenter {
        void onCreate();
    
        void onStart();
    
        void onResume();
    
        void onPause();
    
        void onStop();
    
        void onDestroy();
    }
    

    然后实现接口,在Activity/Fragment的生命周期中调用这个接口,完成工作。

    这种方式完全ojbk。通俗易懂,这里我不评价它的好坏,毕竟没有任何一种解决方案是完美的。所以接下来咱们来看一看官方的Lifecycle是怎样的一种思路。

    Lifecycle

    说破天,这里需要解决的问题是生命周期管理。那么终究还是逃脱不掉一些套路成分在其中。Lifecycle也是如此,从官方的解释中,可见一斑:

    Lifecycle is a class that holds the information about the lifecycle state of a component (like an activity or a fragment) and allows other objects to observe this state.

    短短一段话,我们可以猜测到这里通过观察者模式的思路去对外响应生命周期变化。闲话少说,直接从代码感受一下。

    使用

    从使用上来说,还是比较简单的。实现LifecycleObserver接口:

    // 官方demo
    class MyObserver : LifecycleObserver {
    
        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        fun connectListener() {
            // TODO
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        fun disconnectListener() {
            // TODO
        }
    }
    

    这俩个注解则标志着,当监听组件的onResume()方法被调用,这里我们被注解的方法也会被调用。(当然前提是addObserver了)

    有了观察者了,那我们就去找被观察者。很明显,我们想要观察的对象是拥有生命周期的家伙,比如我们常用的Activity/Fragment。此时我们只需要在onResume()之前的某个实际,把这个Observer,add进去即可,比如在onCreate()中:

    override fun onCreate(savedInstanceState: Bundle?) {
       lifecycle.addObserver(MyObserver())
    }
    

    OK,这样之后我们的MyObserver既可以正常在响应对应生命周期注解下的方法了。

    不过,我相信这样写的朋友,回过来喷我!根本就调不到lifecycle!!

    没错,我们常规的Activitiy/Fragment就是调不到…它压根就没这这个方法。

    androidx

    这里解释一下,上文中lifecyle其实就是调用Activity/Fragment中的这个方法:

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

    有朋友应该提着刀过来了,我tm没有这个方法!兄die,把刀放下,不是没有是import不一样。接下来让我们慢慢来。我使用的这个Fragment的package是这样的:androidx.fragment.app;。看到端倪了吧?androidx,没错,这是为了完美支持JatPack所重新规划出来的包。

    当然,也不一定非要用androidx。

    Fragments and Activities in Support Library 26.1.0 and later already implement the LifecycleOwner interface.

    所以,升库就ok了。这时有小伙伴可能会说了:我不想升库怎么办。这个问题问得好,不想升库,不想升库…就不升呗。

    当然我相信,一定有小伙伴注意到一个问题,那就是getLifecycle()是一个接口,那么也就是说我们可以自己实现?没错是这样…(这tm不废话么)

    这就是我们自定义的关键。

    LifecycleOwner

    假设我们的Activity不支持getLifecycle()咋整?这里直接上官方的代码:

    class="prism language-kotlin">class="token keyword">class MyActivity class="token operator">: class="token function">Activityclass="token punctuation">(class="token punctuation">)class="token punctuation">, LifecycleOwner class="token punctuation">{
        class="token keyword">private class="token keyword">lateinit class="token keyword">var mLifecycleRegistryclass="token operator">: LifecycleRegistry
    
        class="token keyword">override class="token keyword">fun class="token function">onCreateclass="token punctuation">(savedInstanceStateclass="token operator">: Bundleclass="token operator">?class="token punctuation">) class="token punctuation">{
            class="token keyword">superclass="token punctuation">.class="token function">onCreateclass="token punctuation">(savedInstanceStateclass="token punctuation">)
    
            mLifecycleRegistry class="token operator">= class="token function">LifecycleRegistryclass="token punctuation">(class="token keyword">thisclass="token punctuation">)
            mLifecycleRegistryclass="token punctuation">.class="token function">markStateclass="token punctuation">(Lifecycleclass="token punctuation">.Stateclass="token punctuation">.CREATEDclass="token punctuation">)
            
            mLifecycleRegistryclass="token punctuation">.class="token function">addObserverclass="token punctuation">(class="token function">MyObserverclass="token punctuation">(class="token punctuation">)class="token punctuation">)
        class="token punctuation">}
    
        class="token keyword">public class="token keyword">override class="token keyword">fun class="token function">onStartclass="token punctuation">(class="token punctuation">) class="token punctuation">{
            class="token keyword">superclass="token punctuation">.class="token function">onStartclass="token punctuation">(class="token punctuation">)
            mLifecycleRegistryclass="token punctuation">.class="token function">markStateclass="token punctuation">(Lifecycleclass="token punctuation">.Stateclass="token punctuation">.STARTEDclass="token punctuation">)
        class="token punctuation">}
    
        class="token keyword">override class="token keyword">fun class="token function">getLifecycleclass="token punctuation">(class="token punctuation">)class="token operator">: Lifecycle class="token punctuation">{
            class="token keyword">return mLifecycleRegistry
        class="token punctuation">}
    class="token punctuation">}
    

    就这样,结束了。说实话,到这就这的没有什么好讲的了。

    通过代码,我们可以看出来,LifecycleRegistry是我们的被观察者,它被初始化在拥有生命周期的Activity中,而我们的Observer也被add()到其中,此外还有诸如markState(Lifecycle.State.CREATED)的方法调用。

    因此,到这无需多言,各位小伙伴恐怕已经明白了Lifecycle是如何帮我们管理生命周期的了。

    Lifecycle原理代码

    咱们在上述的MyObserver中加了注解,所以先看看注解为我们带来了什么。通过注解生成器,我们可以看到在build中得到了下边这个class:

    class="prism language-java">class="token keyword">public class="token keyword">class class="token class-name">MyObserver_LifecycleAdapter class="token keyword">implements class="token class-name">GenericLifecycleObserver class="token punctuation">{
        class="token keyword">final MyObserver mReceiverclass="token punctuation">;
    
        class="token function">LifecycleObserverDemo_LifecycleAdapterclass="token punctuation">(MyObserver receiverclass="token punctuation">) class="token punctuation">{
            class="token keyword">thisclass="token punctuation">.mReceiver class="token operator">= receiverclass="token punctuation">;
        class="token punctuation">}
    
        class="token annotation punctuation">@Override
        class="token keyword">public class="token keyword">void class="token function">onStateChangedclass="token punctuation">(LifecycleOwner ownerclass="token punctuation">, Lifecycleclass="token punctuation">.Event eventclass="token punctuation">) class="token punctuation">{
            mReceiverclass="token punctuation">.class="token function">onAnyclass="token punctuation">(ownerclass="token punctuation">,eventclass="token punctuation">)class="token punctuation">;
            class="token keyword">if class="token punctuation">(event class="token operator">== Lifecycleclass="token punctuation">.Eventclass="token punctuation">.ON_RESUMEclass="token punctuation">) class="token punctuation">{
                mReceiverclass="token punctuation">.class="token function">connectListenerclass="token punctuation">(class="token punctuation">)class="token punctuation">;
            class="token punctuation">}
    
            class="token keyword">if class="token punctuation">(event class="token operator">== Lifecycleclass="token punctuation">.Eventclass="token punctuation">.ON_PAUSEclass="token punctuation">) class="token punctuation">{
                mReceiverclass="token punctuation">.class="token function">disconnectListenerclass="token punctuation">(class="token punctuation">)class="token punctuation">;
            class="token punctuation">}
        class="token punctuation">}
    
        class="token keyword">public Object class="token function">getReceiverclass="token punctuation">(class="token punctuation">) class="token punctuation">{
            class="token keyword">return mReceiverclass="token punctuation">;
        class="token punctuation">}
    class="token punctuation">}
    

    很清晰,我们能够看到,在onStateChanged(LifecycleOwner owner, Lifecycle.Event event)中通过对应的Event就可以调用到我们MyObserver中注解的方法。

    那么问题来了:onStateChanged被谁调用的呢?通过上边的例子,我们知道想要Observer能够感应生命周期要么使用内置好的Lifecycle(getLifecycle()),要么自己去实现(LifecycleOwner)。接下来咱们就分这俩种情况来看一看具体的实现原理。

    自定义LifecycleOwner

    这一步的源码还是比较的简单直接的,我们可以直接在LifecycleRegistry中的markState(Lifecycle.State.STARTED)一探究竟,一层层的调用下来,我们抛弃一些逻辑判断之后,可以看到一些关键的内容:

    class="prism language-java">class="token keyword">static class="token keyword">class class="token class-name">ObserverWithState class="token punctuation">{
        State mStateclass="token punctuation">;
        GenericLifecycleObserver mLifecycleObserverclass="token punctuation">;
    
        class="token function">ObserverWithStateclass="token punctuation">(LifecycleObserver observerclass="token punctuation">, State initialStateclass="token punctuation">) class="token punctuation">{
            mLifecycleObserver class="token operator">= Lifecyclingclass="token punctuation">.class="token function">getCallbackclass="token punctuation">(observerclass="token punctuation">)class="token punctuation">;
            mState class="token operator">= initialStateclass="token punctuation">;
        class="token punctuation">}
    
        class="token keyword">void class="token function">dispatchEventclass="token punctuation">(LifecycleOwner ownerclass="token punctuation">, Event eventclass="token punctuation">) class="token punctuation">{
            State newState class="token operator">= class="token function">getStateAfterclass="token punctuation">(eventclass="token punctuation">)class="token punctuation">;
            mState class="token operator">= class="token function">minclass="token punctuation">(mStateclass="token punctuation">, newStateclass="token punctuation">)class="token punctuation">;
            class="token comment">// 看到这,没啥好说的了吧?
            mLifecycleObserverclass="token punctuation">.class="token function">onStateChangedclass="token punctuation">(ownerclass="token punctuation">, eventclass="token punctuation">)class="token punctuation">;
            mState class="token operator">= newStateclass="token punctuation">;
        class="token punctuation">}
    class="token punctuation">}
    

    可以看到,这部分会很直白的调用到注解生成class中的onStateChanged(),完成生命周期的感知。

    getLifecycle()

    getLifecycle()的方式,同样是返回了一个LifecycleRegistry。因此,最开始我认为系统因此在对应的生命周期完成对上3.1一样的调用。不过看把发现自己还是太年轻。

    在SupportActivity中,的onCreate方法中,我们可以看到这样的调用:

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

    是不是感觉到一丝丝熟悉?使用Fragment做生命周期分离管理在很多框架中都出现。接下来我们就好好看看这个ReportFragment。

    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }
    
    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);
            }
        }
    }
    
    image

    到此就重新回调到了LifecycleRegistry中的方法了。以上所述就是Jetpack中的Lifecycle管理生命周期;有关更多的Android技术进阶学习,可以参考《Android核心技术手册》这个文档笔记,点击查看里面附有30几个技术板块。

    总结

    这几段代码下来,我相信有的朋友已经差不多了解Lifecycle的思路了。一个很标准的观察者模式:这里的LifecycleRegistry(系统帮我们实现的Lifecycle的实现类),持有想要监听这个LifecycleOwner的Observer。然后通过markState(),去遍历所有Observer,通知其生命周期发生变化。

    当然仅凭这些,对于我们来说还远远不够,因此Google还拿出了ViewModel、LiveData等相辅相成的有趣模块。

    相关文章

      网友评论

        本文标题:Jetpack管理生命周期——Lifecycle

        本文链接:https://www.haomeiwen.com/subject/djgikdtx.html