本文正在参与「金石计划 . 瓜分6万现金大奖」
Hi , 你好 :)
导言
在2022的今天,AndroidX
遍及的情况下,JetPack Lifecycle 也早现已成为了开发中的根底设施,小到 View(扩展库)
,大到 Activity
,都隐藏着它的身影,而了解 Lifecycle
也正是理解 JetPack
组件系列库生命感知规划的根底。
本篇定位中级,将从布景到源码完成,然后理解其背后的规划思想。
导航
看完本篇,你将会搞清以下问题:
-
Lifecycle
的前世此生; -
Lifecycle
能够干什么; -
Lifecycle
源码解析;
布景
在开端前,咱们先聊聊关于 Lifecycle
的前世此生,然后便于咱们更好的理解 Lifecycle
存在的含义。
洪荒之时
在 Lifecycle
之前(不排除现在),假如咱们要在某个生命周期去履行一些操作时,常常会在Act或许Fragment写许多模版代码,如下两个示例:
- 比方,有一个定时器,咱们需求在
Activity
封闭时将其封闭,然后防止因而导致的内存问题,所以咱们自然会在onDestory()
中去stop一下。这些事看起来似乎不费事,但假如是一个重复多处运用的代码,细心的开发者会将其独自抽离成为一个 case ,然后经过组合的办法降低咱们主类中的逻辑,但不可防止咱们仍然还要存在很多模版代码,由于每次都需求onStop()
整理或许其他操作(除非写到base,但不可接受☹️)。
假如能不需求开发者自己手动,该有多好?
- 在老版别的友盟中,咱们常常甚至需求在基类的
Activity
中复写onResume()
、onPause()
等办法,这些工作说费事也不费事,但总是感觉很不舒畅。不过,有经历的开发者必定会想喷,为什么一个三方库,你就自己不会经过application.registerActivityLifecycleCallbacks
监听吗。
留意,Application有监听大局Act生命周期的办法,Act也有这个办法。
盘古开天
在 JetPack 之前,Android
一向秉承着传统的 MVC 架构,即 xml
作为 View, Activity
作为 Control ,Model
层由数据模型或许仓库而定。虽然说官方曾经有一个MVP的示例,但真正用的人并不多。再加上官方一向也没推荐过 Android
的架构攻略,这就导致传统的Android开发办法和系统的碎片化相同☹️,五花八门。跟着时间的推移,眼看前端的MVVM已更加老练,后有Flutter,再加上开发者的需求等布景下,Google于2017年发布了新的开发架构: AAC,全名 Architecture,而且伴跟着一系列相关组件,然后协助开发者提高开发体验,降低错误概率,削减模版代码。
而本篇的主题 Lifecycle
正是其间作为根底设施的存在,在 sdk26 之后,更是被写入了根底库中。
那Lifecycle到底是干什么的呢?
Lifecycle
做的工作很简单,其便是用于检测组件(Fragment
、Act
) 的生命周期,然后不必强依赖于Activity
与Fragment
,协助开发者降低模版代码。
常见用法
在官网中,关于 Lifecycle
的生命周期感知的整个流程如下所示:
Api介绍
相关字段
-
Event
生命周期事情,对应详细的生命周期:
ON_CREATE
,ON_START
,ON_RESUME
,ON_PAUSE
,ON_STOP
,ON_DESTROY
,ON_ANY
-
State
生命周期状况节点,与 Event 紧密相关,Event 是这些结点的详细边界,换句话说,State 代表了这一时间的详细状况,其相当于一个规模集,在这个规模里,都是这个状况。而Event代表这一状况集里边触发的详细事情是什么。
INITIALIZED
结构函数初始化时,且未收到 `onCreate()` 事情时的状况;
CREATED
在 `onCreate()` 调用之后,`onStop()` 调用之前的状况;
STARTED
在 `onStart()` 调用之后,`onPause()` 调用之前的状况;
RESUMED
在 `onResume()` 调用时的状况;
`DESTROYED`
`onDestory()` 调用时的状况;
相关接口
-
LifecycleObserver
根底
Lifecycler
完成接口,一般调用不到,可用于自定义的组件,然后防止在Act
或许Fragment
中的模版代码,例如ViewTreeLifecyleOwner
; -
LifecycleEventObserver
能够接受所有生命周期改变的接口;
-
FullLifecycleObserver
用于监听生命周期改变的接口,提供了
onCreate()
、onStart()
、onPause()
、onStop()
、onDestory()
、onAny()
; -
DefaultLifecycleObserver
FullLifecycleObserver
的默许完成版别,比较前者,增加了默许null
完成;
举个栗子
如下所示,经过完成 DefaultLifecycleObserver
接口,咱们能够在中重写咱们想要监听的生命周期办法,然后将业务代码从主类中拆离出来,且更便于复用。最终在相关类中直接运用 lifecycle.addObserver()
办法增加实例即可,这也是google推荐的用法。
上述示例中,咱们运用了
viewLifecycle
,而不是lifecycle
,这儿顺便提一下。见名之意,前者是视图(view)生命周期,后者则对错视图的生命周期,详细差异如下:
viewLifecycle
只会在 onCreateView-onDestroyView 之间有效。
lifecycle
则是代表 Fragment 的生命周期,在视图未创立时,onCreate()
,onDestory()
时也会被调用到。
或许你有某个自定义View,想感知Fragment或许Act的生命周期,然后做一些工作,比方Banner组件等,与上面示例类似:
当然你也能够选择依赖:androidx.lifecycle:lifecycle-runtime 扩展库。
然后运用
view.findViewTreeLifecycleOwner()
的扩展函数取得一个LifecycleOwner
,然后在View内部自行监听生命周期,革除在Activity手动增加观察者的模版代码。
lifecycle.addObserver(view)
源码解析
Lifecycle
在官方的解说里,Lifecycle 是一个类,用于存储有关组件(Act或Fragment)声明周期状况新的类,并答应其他目标观察此类。
直接去看 Lifecycle
的源码,其完成办法如下:
总体规划如上所示,比较简单,便是观察者模式的接口模版:
运用者完成
LifecycleObserver
接口(),然后调用 addObserver() 增加到观察者列表,撤销观察者时调用 rmeoveObserver() 移除掉即可。在相应的生命周期变化时,遍历观察者列表,然后告诉完成了LifecycleObserver
的实例,然后调用相应的办法。
由于其是一个抽象类,所以咱们调用的一般都是它的详细完成类,也便是 LifecycleRegistry
,目前也是其的唯一完成类。
LifecycleRegistry
Lifecycle
的详细完成者,正如其名所示,首要用于办理当时订阅的 观察者目标 ,所以也承担了 Lifecycle
详细的完成逻辑。由于源码较长,所以咱们做了一些删减,只需重视主流程即可,伪代码如下:
public class LifecycleRegistry extends Lifecycle {
// 生命周期观察者map,LifecycleObserver是观察者接口,ObserverWithState详细的状况分发的包装类
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap;
// 当时生命周期状况
private State mState = INITIALIZED;
// 持有生命周期的提供商,Activity或许Fragment的弱引用
private final WeakReference<LifecycleOwner> mLifecycleOwner;
// 当时正在增加的观察者数量,默许为0,超越0则以为多线程调用
private int mAddingObserverCounter = 0;
// 是否正在分发事情
private boolean mHandlingEvent = false;
// 是否有新的事情产生
private boolean mNewEventOccurred = false;
// 存储主类的事情state
private ArrayList<State> mParentStates = new ArrayList<>();
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
// 初始化状况,destory or init
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
// 初始化实际分发状况的包装类
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
// 将观察者增加到详细的map中,假如现已存在了则回来之前的,不然创立新的增加到map中
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
// 假如上一步增加成功了,putIfAbsent会回来null
if (previous != null) {
return;
}
// 假如act或许ff被回收了,直接return
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
return;
}
// 当时增加的观察者数量!=0||正在处理事情
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
// 取得观察者当时的状况
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
// 假如当时观察者状况小于当时生命周期所在状况&&这个观察者现已被存到了观察者列表中
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
// 保存当时的生命周期状况
pushParentState(statefulObserver.mState);
// 回来当时生命周期状况对应的接下来的事情序列
final Event event = Event.upFrom(statefulObserver.mState);
...
// 分发事情
statefulObserver.dispatchEvent(lifecycleOwner, event);
// 移除当时的生命周期状况
popParentState();
// 再次取得当时的状况,以便继续履行
targetState = calculateTargetState(observer);
}
// 处理一遍事情,保证事情同步
if (!isReentrance) {
sync();
}
// 回归默许值
mAddingObserverCounter--;
}
...
static class ObserverWithState {
State mState;
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, State initialState) {
// 初始化事情观察者
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = event.getTargetState();
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
...
}
咱们要点重视的是 addObserver()
即订阅生命周期改变时的逻辑,详细如下:
- 先初始化当时观察者的状况,默许两种,即
DESTROYED
(销毁) 或许INITIALIZED
(无效),别离对应onDestory()
和onCreate()
之前; - 初始化 状况观察者(ObserverWithState) ,内部运用
Lifecycling.lifecycleEventObserver()
将咱们传递进来的 生命周期观察者(LifecycleObser) 包装为一个 生命周期[事情]观察者LifecycleEventObserver,然后在状况改变时触发事情告诉; - 将第二步生成的状况观察者增加到缓存map中,假如之前现已存在,则停止接下来的操作,不然继续初始化;
- 调用
calculateTargetState()
取得当时真正的状况。 - 开端事情轮训,假如 当时观察者的状况小于此刻真正的状况 && 观察者现已被增加到了缓存列表 中,则取得当时观察者下一个状况,并触发相应的事情告诉
dispatchEvent()
,然后继续轮训。直到不满足判别条件;
需求留意的是, 关于状况的判别,这儿运用了compareTo() ,然后判别当时状况枚举是否小于指定状况。
Activity中的完成
Tips:
写过权限检测库的小伙伴,应该很熟悉,为了防止在 Activity
中手动完成 onActivityRequest()
,然后完成以回调的办法取得权限成果,咱们往往会运用一个通明的 Fragment
,然后将模版办法拆离到独自类中,而这种完成办法正是组合的思想。
而 Lifecycle
在 Activity 中的完成正是上述的办法。
如下所示,当咱们在 Activity
中调用 lifecycle
目标时,内部实际上是调用了 ComponentActivity.mLifecycleRegistry,详细逻辑如下:
不难发现,在咱们的 Activity
初始化时,相应的 LifecycleRegistry
现已被初始化。
在上面咱们说过,为了防止对基类的入侵,咱们一般会用组合的办法,所以这儿的 ReportFragment
正是 Lifecycle
在 Activity
中详细的逻辑承载方,详细逻辑如下:
ReportFragment.injectIfNeededIn
内部会对sdk进行判别,对应着两套流程,关于 sdk>=29 的,经过注册 Activity.registerActivityLifecycleCallbacks()
事情完成监听,关于 sdk<29 的,重写 Fragment
相应的生命周期办法完成。
ReportFragment 详细逻辑如下:
Fragment中的完成
直接去 Fragment.lifecycle
中看一下即可,伪代码如下:
总结如下:lifecycle
实例会在 Fragment 结构函数 中进行初始化,而 mViewLifecycleOwner
会在 performCreateView() 履行时初始化,然后在相应的 performXxx 生命周期履行时,调用相应的 lifecycle.handleLifecycleEvent()
然后完成事情的告诉。
总结
Lifecycle
作为 JetPack
的基石,而理解其是咱们贯穿相应生命周期的关键所在。
关于生命周期的告诉,Lifecycle
并没有选用直接告诉的办法,而是选用了 Event(事情) + State(状况) 的规划办法。
- 关于外部生命周期订阅者而言,只需求重视事情
Event
的调用;- 而关于
Lifecycle
而言,其内部只重视State
,并将生命周期区分为了多个阶段,每个状况又代表了一个事情集,然后关于外部调用者而言,无需拘泥于当时详细的状况是什么。
在详细的完成底层上面:
- 在
Activity
中,选用组合的办法而非继承,在 Activity.onCreate() 触发时,初始化了一个通明Fragment
,然后将逻辑存于其间。关于sdk>=29的版别,由于Activity
自身有监听生命周期的办法,然后直接注册监听器,并在相应的会调用触发生命周期事情更新;关于sdk<29的版别,由于需求兼容旧版别,所以重写了Fragment
相应的生命周期办法,然后完成手动触发更新咱们的生命周期观察者。- 在
Fragment
中,会在Fragment
结构函数中初始化相应的Lifecycle
,并重写相应的生命周期办法,然后触发事情告诉,完成生命周期观察者的更新。
每逢咱们调用 addObserver()
增加新的观察者时:
内部都会对咱们的观察者进行包装,并将其包装为一个详细的事情观察者
LifecycleEventObserver
,以及生成当时的观察者对应的状况实例(内部持有LifecycleEventObserver
),并将其保存到 缓存map 中。接着会去比照当时的 观察者的状况 和 lifecycle此刻实际状况 ,假如 当时观察者状况<lifecycle对应的状况 ,则触发相应Event
的告诉,并 更新此观察者对应的状况 ,不断轮训,直到当时观察者状况 >=lifecycle
对应状况。
参阅
- Android-运用生命周期感知型组件处理生命周期
关于我
我是 Petterp ,一个 Android工程师 ,假如本文对你有所协助,欢迎点赞支撑,你的支撑是我继续创作的最大鼓舞!