Jetpack组件之生命周期感知组件——LifeCycles

LifeCycles

1、Lifecycles 简介

Lifecycles 即生命周期,属于 Jetpack 架构组件之一的 Lifecycles 组件是可以为其它组件提供生命周期感知能力的一个组件,而具备了生命周期感知能力的组件就叫生命周期感知组件

那么什么是生命周期感知能力呢?

我们知道四大基础组件有生命周期,能感知这些生命周期的组件就具备了生命周期感知能力,所以我认为以前我们使用的 MVP 模式中的 Presenter 如果它通过接口等方式间接获得了 Activity 的生命周期,它也算是一个生命周期感知组件,但是这种获取生命周期的方式和 Lifecycles 比起来还是太 low 了,我们接着对比传统生命周期感知方式,聊一聊为什么使用 Lifecycles 组件。

2、为什么需要 Lifecycles 组件 ?

我们知道,一个 Android App 之所以能够完成一系列复杂任务,都是基于各个基础组件之间的密切配合,我们熟知的四大组件(Activity、Service、Broadcast、Content Provider)是有生命周期的,并且 Android 的操作系统层或者 FrameWork 框架层会为其提供相应的回调,以便程序在不同的状态下做相对正确的事;

而普通的组件或者我们自己开发的一些组件就没有这个待遇了,我们通常需要在合适的时候,手动将这些第三方组件的状态控制方法,诸如启动/关闭/注册/拆除等,添加到具备生命周期的组件的回调中去才能使它们正确工作。

然后,随着时间推移版本迭代,引用的第三方组件越来越多,你的代码逐渐变成了这样

override fun onStart() {
    a.init()
    b.start()
    c.initialize()
    ...
}
...
override fun onStop(){
    if(a!=null) a.remove()
    if(b!=null&&b.c!=null) {
        b.c.tearDown()
        b.stop()
    } 
    c.stop()
    ...
}

你可能会在 Presenter 中完成这一系列操作,但这其实没有解决根本问题:随着第三方组件越来越多的引入,你的 Presenter 也越来越难以维护和测试。而且还可能出现内存泄露的情况

override fun onStart() {
        Util.checkUserStatus { result ->
        // 此回调可能在 onStop 之后被调用
                if(result){
                b.start()
            }
        }                     
}
...
override fun onStop(){
        b.stop()
}

2.1、自定义方法举例

也许有点抽象,举个例子说明一下,比如有个需求,需要在一个界面比较频繁更新地理位置信息。当Activity走了onstop之后,你应该也要暂停更新地理位置,或者当Activity走destroy后,你要释放一些资源。下面用一些代码实例解析一下:

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) 					  
    {
        // ...
    }
<span class="token keyword">void</span> <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">// 开始连接位置服务</span>
<span class="token punctuation">}</span>

<span class="token keyword">void</span> <span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">// 停止连接位置服务</span>
<span class="token punctuation">}</span>

<span class="token keyword">void</span> <span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token comment">//释放资源</span>
<span class="token punctuation">}</span>

}

class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;

@Override
public <span class="token keyword">void</span> <span class="token function">onCreate</span><span class="token punctuation">(</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    myLocationListener <span class="token operator">=</span> new <span class="token function">MyLocationListener</span><span class="token punctuation">(</span>this<span class="token punctuation">,</span> new <span class="token function">Callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
        <span class="token comment">//回调更新UI</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

@Override
public <span class="token keyword">void</span> <span class="token function">onStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    super<span class="token punctuation">.</span><span class="token function">onStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    myLocationListener<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//绑定actiivty的onStart周期函数</span>
<span class="token punctuation">}</span>

@Override
public <span class="token keyword">void</span> <span class="token function">onStop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    super<span class="token punctuation">.</span><span class="token function">onStop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    myLocationListener<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//绑定actiivty的onStop周期函数</span>
<span class="token punctuation">}</span>

@Override
public <span class="token keyword">void</span> <span class="token function">onDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    super<span class="token punctuation">.</span><span class="token function">onDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    myLocationListener<span class="token punctuation">.</span><span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token comment">//绑定actiivty的onDestroy周期函数</span>
<span class="token punctuation">}</span>

随着第三方组件越来越多的引入,越来越难以维护和测试

3、 Lifecycles 组件 的使用

  • 1、实现LifecycleObserver接口
  • 2、LifeCycleaddObserver方法添加观察者
  • 3、通过@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)注解方式给方法加上注解,就实现了生命周期的调用
class MyLocationListener implements LifecycleObserver{
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }
@<span class="token function">OnLifecycleEvent</span><span class="token punctuation">(</span>Lifecycle<span class="token punctuation">.</span>Event<span class="token punctuation">.</span>ON_START<span class="token punctuation">)</span>
<span class="token keyword">void</span> <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">// 开始连接位置服务</span>
<span class="token punctuation">}</span>

@<span class="token function">OnLifecycleEvent</span><span class="token punctuation">(</span>Lifecycle<span class="token punctuation">.</span>Event<span class="token punctuation">.</span>ON_STOP<span class="token punctuation">)</span>
<span class="token keyword">void</span> <span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    <span class="token comment">// 停止连接位置服务</span>
<span class="token punctuation">}</span>

@<span class="token function">OnLifecycleEvent</span><span class="token punctuation">(</span>Lifecycle<span class="token punctuation">.</span>Event<span class="token punctuation">.</span>ON_DESTROY<span class="token punctuation">)</span>
<span class="token keyword">void</span> <span class="token function">destroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
    <span class="token comment">//释放资源</span>
<span class="token punctuation">}</span>

}

class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;

@Override
public <span class="token keyword">void</span> <span class="token function">onCreate</span><span class="token punctuation">(</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    myLocationListener <span class="token operator">=</span> new <span class="token function">MyLocationListener</span><span class="token punctuation">(</span>this<span class="token punctuation">,</span> new <span class="token function">Callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
        <span class="token comment">//回调更新UI</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">getLifecycle</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addObserver</span><span class="token punctuation">(</span>myLocationListener<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

有关生命周期管理 Google说了要在ViewModel中处理数据逻辑 但不包括网络请求,尽量不要传递Activity的上下文和View的上下文避免内存泄漏,尽量不要再Activity或者Fragment中处理数据和逻辑,保持干净。当之后学完ViewModel和LiveData 还有DataBinding之后,就会发现,UI显示的处理和异常的处理真的方便。

4、 Lifecycles 组件 原理

在这里插入图片描述
Java 大白话讲解设计模式之 – UML类图

看下FragmentLifecycleOwnerLifecycleObserverLifecycle之间的类关系图。

  • Lifecycle组件成员Lifecycle被定义成了抽象类,LifecycleOwnerLifecycleObserver被定义成了接口;
  • Fragment实现了LifecycleOwner接口,该只有一个返回Lifecycle对象的方法getLifecyle()
  • FragmentgetLifecycle()方法返回的是继承了抽象类Lifecycle的LifecycleRegistry
  • LifecycleRegistry中定义嵌套类ObserverWithState,该类持有GenericLifecycleObserver对象,而GenericLifecycleObserver是继承了LifecycleObserver的接口。
  • Lifecycle:Lifecycle是一个持有组件生命周期状态(如Activity或Fragment)的信息的类,并允许其他对象观察此状态。
  • Event :从框架和Lifecycle类派发的生命周期事件。这些事件映射到活动和片段中的回调事件
  • State :由Lifecycle对象跟踪的组件的当前状态。

4.1、LifeCycle中两个重要的接口

LifecycleOwner (重要)Lifecycle持有者

  • 实现该接口的类持有生命周期(Lifecycle对象),该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。

LifecycleObserver(重要)Lifecycle观察者

  • 实现该接口的类,通过注解的方式,可以通过LifecycleOwneraddObserver(LifecycleObserver o)方法注册,被注册后,LifecycleObserver便可以观察到LifecycleOwner的生命周期事件。
4.1.1、LifecycleOwner(生命周期持有者接口)

官网介绍:LifecycleOwner是一个单一的方法接口,表示该类有一个Lifecycle。它有一个方法,getLifecycle()这个方法 必须由这个类来实现。如果您试图管理整个应用程序进程的生命周期,请参阅 ProcessLifecycleOwner。该接口从各个类(如Fragment和AppCompatActivity)抽象生命周期的所有权,并允许编写与它们一起工作的组件。

  • 任何自定义应用程序类都可以实现LifecycleOwner接口
  • 实现LifecycleObserver的组件与实现LifecycleOwner的组件无缝协作,因为所有者可以提供生命周期,观察者可以注册以观看

简单来说,LifecycleOwner就是一个接口,谁继承了它,就持有了lifecycle对象。然后就可以调用getLifecycle()方法获取继承了抽象类Lifecycle的LifecycleRegistry,然后调用 addObserver(@NonNull LifecycleObserver observer) 方法来注册监听。

这样,该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。

注意:

Support Library 26.1.0 及其以后的版本,Activity 和Fragment 已经实现了LifecycleOwner 接口,所以,我们可以直接在Activity 和Fragment中使用getLifecycle()方法来获取lifecycle对象,来添加观察者监听。

4.1.2、LifecycleObserver(生命周期观察者接口)

LifecycleObserver 是一个观察者接口,实现了它,可以通过注解或者继承的方式,来管理声明周期的监听。只要在持有lifecycle的类中注册了它,当声明周期发生变化时,它就能收到,进行我们自定义的操作。
两种实现方式:

  • 实现DefultLifecyceObserver接口,然后重写里面生命周期方法;
  • 直接实现LifecycleObserver接口,然后通过注解的方式来接收生命周期的变化;

4.2、时序图

对于Fragment、Lifecycle、LifecycleOwner、LifecycleObserver的关系有了一定了解后,可以看一个更直观的图,也就是下面的时序图:
在这里插入图片描述

  • 我们在Fragment(AppCompatActivity也一样)中调用getLifecycle()方法得到LifecycleRegistry对象,然后调用addObserver()方法并将实现了LifecycleObserver接口的对象作为参数传进去。这样一个过程就完成了注册监听的过程。
  • 后续就是Fragment生命周期变化时,通知LifecycleObserver的过程:
    • FragmentperformXXX()、onXXX()方法;
    • LifecycleRegistryhandleLifecycleEvent()方法;LifecycleObserveronXXX()方法。
  • Fragment中performCreate()、performStart()、performResume()会先调用自身的onXXX()方法,然后再调用LifecycleRegistry的handleLifecycleEvent()方法;
  • 而在performPause()、performStop()、performDestroy()中会先LifecycleRegistryhandleLifecycleEvent()方法,然后调用自身的onXXX()方法。

比如上面的例子中,打印出来的结果也确实符合我们的分析,打印结果如下:

12-01 14:12:59.250 1398-1398/com.shymanzhu.architecture D/MainActivity: onCreate: 
12-01 14:12:59.342 1398-1398/com.shymanzhu.architecture D/MainPresenter: onCreate: 
12-01 14:12:59.345 1398-1398/com.shymanzhu.architecture D/MainActivity: onStart: 
12-01 14:12:59.345 1398-1398/com.shymanzhu.architecture D/MainPresenter: onStart: 
12-01 14:12:59.346 1398-1398/com.shymanzhu.architecture D/MainActivity: onResume: 
12-01 14:12:59.346 1398-1398/com.shymanzhu.architecture D/MainPresenter: onResume: 
12-01 14:12:59.601 1398-1412/com.shymanzhu.architecture D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
12-01 14:12:59.609 1398-1398/com.shymanzhu.architecture I/imx6.gralloc: open gpu gralloc module!
12-01 14:12:59.847 1398-1412/com.shymanzhu.architecture I/OpenGLRenderer: Initialized EGL, version 1.4
12-01 14:13:27.348 1398-1398/com.shymanzhu.architecture D/MainPresenter: onPause: 
12-01 14:13:27.349 1398-1398/com.shymanzhu.architecture D/MainActivity: onPause: 
12-01 14:13:28.265 1398-1398/com.shymanzhu.architecture D/MainPresenter: onStop: 
12-01 14:13:28.266 1398-1398/com.shymanzhu.architecture D/MainActivity: onStop: 
12-01 14:13:28.267 1398-1398/com.shymanzhu.architecture D/MainPresenter: onDestroy: 
12-01 14:13:28.267 1398-1398/com.shymanzhu.architecture D/MainActivity: onDestroy: 

其实这个Lifecycle组件是设计模式中观察者模式的例子

参考

1、Jetpack系列学习笔记整理一 之LifeCycles
2、Android Jetpack架构组件之 Lifecycles(使用篇)
3、Android Jetpack组件之Lifecycles库详解
4、Android Jetpack - Lifecycles
5、Android 架构组件(一)——Lifecycle
6、Android官方架构组件:Lifecycle详解&原理分析

原文链接:https://blog.csdn.net/JMW1407/article/details/121529984

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值