Jetpack 是 Google 官方力推的一个套件,它由许多库组成,这些库的出现意在帮助开发者简化业务逻辑之外的部分,包括开发架构优化、避免内存泄漏、性能优化等方面。之前我也零零散散用到过一些,现在准备做个记录,帮助自己梳理以及再次熟悉一下各组件。
首先回顾一下 Lifecycle。
一、Lifecycle 有什么用
Lifecycle,生命周期,从名字上来看就知道它与生命周期紧密相连,一提到生命周期,我们首先想到的就是 Activity、Fragment、Service 等。没错,Lifecycle 这个组件就是用来帮助我们更方便的做一些与生命周期绑定的操作,主要用于 Activity 或 Fragment 之间,androidx 下的 ComponentActivity 和 Fragment 已经默认实现了 LifecycleOwner。当然我们也可以自己实现 LifecycleOwner,但很少会有这样的需求。
我们日常开发中常常会在 Activity 的生命中做一些初始化资源和释放资源的操作,经典的 MVP 架构也是需要在 Activity 的生命周期中进行 v 层与 p 层的绑定解绑操作,这些操作呢主要是为了及时释放资源,避免内存泄漏,所以是必须注意的。但是要是这些操作全都写到 Activity 中,越来越多就会导致 Activity 臃肿,因此 Lifecycle 应运而生,帮助我们从 Activity 中剥离这些代码。
举个例子,我们在使用 MediaPlayer 的时候,通常需要在 onPause() 中暂停播放,在 onDestroy() 中释放播放器,如果我们使用 Lifecycle 来自定义一个播放器,就不需要在 Activity 的生命周期中做些操作了,只需要在创建播放器实例关联一下 LifecycleObserver 即可。
二、LifecycleObserver 怎么用
生命周期观察者,可以观察 Activity、Fragment 及其他 LifecycleOwner 的实现类,在它们对应的生命周期时可以感知到,进而做一些自己的操作,比如初始化资源、释放资源、开启动画、停止动画等。
LifecycleObserver 的使用其实很简单,首先在 gradle 的 dependencies 中添加依赖:
def lifecycle_version = "2.4.0"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
然后定义一个实现观察者类,也就是我们的业务类,要实现观察生命周期有两种方式:
- 实现 LifecycleObserver 接口,在自己定义的方法上,加入 OnLifecycleEvent 注解,然后被观察者触发相应生命周期的时候就会调用对应的方法,但是这种方式已经被弃用了。
package com.qinshou.jetpackdemo.lifecycle import androidx.lifecycle.* class TestLifecycleObserver : LifecycleObserver { companion object { private const val TAG = "TestLifecycleObserver" } @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun init() { // do sth. } @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun release() { // do sth. } }
- 实现 DefaultLifecycleObserver 接口,覆写它的 onCreate、onStart 等方法,被观察触发相应生命周期的时候会调用对应的方法:
package com.qinshou.jetpackdemo.lifecycle import android.util.Log import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner class TestLifecycleObserver : DefaultLifecycleObserver { companion object { private const val TAG = "TestLifecycleObserver" } override fun onCreate(owner: LifecycleOwner) { super.onCreate(owner) Log.i(TAG, "onCreate") } override fun onStart(owner: LifecycleOwner) { super.onStart(owner) Log.i(TAG, "onStart") } override fun onResume(owner: LifecycleOwner) { super.onResume(owner) Log.i(TAG, "onResume") } override fun onPause(owner: LifecycleOwner) { super.onPause(owner) Log.i(TAG, "onPause") } override fun onStop(owner: LifecycleOwner) { super.onStop(owner) Log.i(TAG, "onStop") } override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) Log.i(TAG, "onDestroy") owner.lifecycle.removeObserver(this) } }
从观察者的示例可以看出它的使用很简单,只需要实现一个接口,然后在对应方法做对应操作就行了,对应到实际开发中,我们就可以在 onPause 中做诸如停止动画,暂停播放,在 onDestroy 中做一些释放资源等操作。
三、LifecycleOwner 怎么用
一般情况下,我们需要观察有生命周期的对象都是 Activity 或者 Fragment,它们已经默认实现了 LifecycleOwner 接口,它们是怎么触发 Lifecycle 对应的生命周期方法的,一会儿再浅析一下,这里先示例一下如果我们需要自定义 LifecycleOwner 应该怎么去做。就个人经验来说,这种情况其实很少,因为如果我们要定义一个对象有生命周期的话,那它应该也是跟系统的生命周期有所关联的,所以应该还是逃不开 Activity 和 Fragment,这里仅了解一下 LifecycleOwner 怎么用就行了。
自定义一个类实现 LifecycleOwner 接口,然后在合适时机调用 LifecycleRegistry.handleLifecycleEvent() 处理相应生命周期即可:
package com.qinshou.jetpackdemo.lifecycle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
class TestLifecycleOwner : LifecycleOwner {
private val lifecycleRegistry by lazy { LifecycleRegistry(this) }
override fun getLifecycle(): Lifecycle {
return lifecycleRegistry
}
fun handleOnCreate() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
}
fun handleOnStart() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)
}
fun handleOnResume() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
}
fun handleOnPause() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE)
}
fun handleOnStop() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)
}
fun handleOnDestroy() {
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
}
}
我们想要让 LifecycleOwner 处于某个生命周期,只需要调用 handleLifecycleEvent() 传入即可。可以写几个按钮分别调用上面定义的方法,然后查看观察者对应的生命周期的方法回调。代码太简单这里就不贴了,文章底部会有 demo 项目的链接。
需要注意的是,当我们按照顺序(ON_CREATE->ON_START->ON_RESUME->ON_PAUSE->ON_STOP->ON_DESTROY)设置 LifecycleOwner 的生命周期的时候没问题,设置哪个生命周期,观察者对应的方法就会回调,但是当:
- 我们重复设置同一个生命周期的时候,只有第一次会回调;
- 跳跃设置生命周期,比如从 ON_CREATE 直接到 ON_RESUME,或者从 ON_CREATE 直接到 ON_PAUSE,甚至往回设置之前的生命周期的时候,比如从 ON_RESUME 设置到 ON_CREATE 时,回调的并不是设置的那个生命周期。
这两点其实可以理解,在 Activity 中处于某个生命周期的时候,该生命周期也不会重复回调。而且 Activity 都是成对的,都是顺序调用的,所以不存在跨周期的情况。当我们自定义 LifecycleOwner 这样去干的时候,代码里面是怎么去拦截的呢?其实很简单,会有一个生命周期同步的步骤,查看 handleLifecycleEvent() 方法的源码:
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
enforceMainThreadIfNeeded("handleLifecycleEvent");
moveToState(event.getTargetState());
}
这个方法里面强制要求切换生命周期必须在主线程中,然后通过 event 去获取对应的 state:
public Lifecycle.State getTargetState() {
switch (this) {
// ON_CREATE 和 ON_STOP 其实是同一个 State
case ON_CREATE:
case ON_STOP:
return Lifecycle.State.CREATED;
// ON_START 和 ON_PAUSE 其实是同一个 State
case ON_START:
case ON_PAUSE:
return Lifecycle.State.STARTED;
case ON_RESUME:
return Lifecycle.State.RESUMED;
case ON_DESTROY:
return Lifecycle.State.DESTROYED;
case ON_ANY:
break;
}
throw new IllegalArgumentException(this + " has no target state");
}
再调用了 moveToState() 方法:
private void moveToState(Lifecycle.State next) {
if (mState == next) {
return;
}
mState = next;
// 如果正在处理生命周期,直接 return
if (mHandlingEvent || mAddingObserverCounter != 0) {
mNewEventOccurred = true;
// we will figure out what to do on upper level.
return;
}
mHandlingEvent = true;
sync();
mHandlingEvent = false;
}
这个方法里面比较重要的就是 sync() 方法,就是在这个方法里面,来决定处于某个生命周期时,如何去分发回调各观察者的:
private void sync() {
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already"
+ "garbage collected. It is too late to change lifecycle state.");
}
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(lifecycleOwner);
}
Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
该方法中会将要设置的生命周期与最早和最新的生命周期比较,进行一个顺推和逆推,在顺推和逆推的过程再去回调各观察者的,如果设置的生命周期一样,就不会进行这个过程,所以也就不会重复调用了,也就解决了第一个疑问。
如果我们之前设置的 ON_PAUSE,按照 getTargetState() 方法当前应该处于 STARTED 状态,这时候再设置 ON_CREATE,那按照 getTargetState() 方法就应该设置为 CREATED 状态,但是明显 CREATED 是要早于 STARTED,所以会进入 backwardPass 方法进行一个逆推:
private void backwardPass(LifecycleOwner lifecycleOwner) {
Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> descendingIterator =
mObserverMap.descendingIterator();
while (descendingIterator.hasNext() && !mNewEventOccurred) {
Map.Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next();
ObserverWithState observer = entry.getValue();
while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred
&& mObserverMap.contains(entry.getKey()))) {
Event event = Event.downFrom(observer.mState);
if (event == null) {
throw new IllegalStateException("no event down from " + observer.mState);
}
pushParentState(event.getTargetState());
observer.dispatchEvent(lifecycleOwner, event);
popParentState();
}
}
}
逆推中关注一下 downFrom() 方法,该方法传入的是 observer 当前的状态,按照上面的假设,传入的应该是 STARTED:
public static Event downFrom(@NonNull State state) {
switch (state) {
case CREATED:
return ON_DESTROY;
case STARTED:
return ON_STOP;
case RESUMED:
return ON_PAUSE;
default:
return null;
}
}
可以看到在这个方法中,如果是 STARTED,那逆推的结果应该是 ON_STOP,所以当我们处于 ON_PAUSE 状态的时候设置 ON_CREATE 的话,实际上回调的应该是 ON_STOP 这个生命周期对应的方法,这也就解决了第二个疑问。
顺推的过程类似,就不举例了。
四、为什么在 onResume 中 addObserver 还会回调 onCreate()
通常来说,我们会在界面创建的时候就添加观察者,也就是在 onCreate() 中去添加,但是当我们在 onResume() 甚至写一个按钮等待页面创建完成后再点击按钮去添加观察者,这时候会发现 onCreate()、onStart()、onResume() 都回调了,这相当于之前的回调都是粘性事件了,这是怎么回事呢?
这个问题的原因还得在源码中去寻找答案,一切都从添加观察者起,那就先看看 addObserver() 方法:
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
enforceMainThreadIfNeeded("addObserver");
Lifecycle.State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
// 创建一个 ObserverWithState 对象,只要被观察者没有处于 DESTROYED 状态,则 initialState 为 INITIALIZED
LifecycleRegistry.ObserverWithState statefulObserver = new LifecycleRegistry.ObserverWithState(observer, initialState);
// 检查之前是否有添加过该观察者,如果有则直接 return
LifecycleRegistry.ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
// it is null we should be destroyed. Fallback quickly
return;
}
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
Lifecycle.State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
// 会比较 statefulObserver 的当前状态和目标状态,如果目标状态此时为 RESUMED,则
// statefulObserver 当前状态为 INITIALIZED,必然会进这个循环里面
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
// 根据 statefulObserver 当前状态决定 Event,upFrom() 方法在下面贴出
final Lifecycle.Event event = Lifecycle.Event.upFrom(statefulObserver.mState);
if (event == null) {
throw new IllegalStateException("no event up from " + statefulObserver.mState);
}
// 分发事件,并在该方法中给 statefulObserver 的 mState 属性重新赋值
statefulObserver.dispatchEvent(lifecycleOwner, event);
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}
public static Event upFrom(@NonNull State state) {
switch (state) {
case INITIALIZED:
return ON_CREATE;
case CREATED:
return ON_START;
case STARTED:
return ON_RESUME;
default:
return null;
}
}
从这两个方法中就可以明白了,如果被观察对象处于 RESUMED 状态,此时添加一个观察者,则它的默认状态为 INITIALIZED,而目标状态又是 RESUMED,那就会进入 while 循环中,第一次循环根据观察者的 INITIALIZED 状态,返回的 Event 为 ON_CREATE,然后通过 dispatchEvent () 方法回调观察者的 onCreate() 方法,在 dispatchEvent() 方法中又会通过 event 给 statefulObserver 的 mState 属性重新赋值(参考上面的 getTargetState() 方法),此时赋值为 CREATED,仍然比 RESUMED,继续循环,直到 statefulObserver 的 mState 与目标状态一样为止。
所以就算后添加的观察者,只要被观察者没有被销毁,那么从 INITIALIZED 被观察者的当前状态之间的生命周期对应的回调都会走一遍。
五、Activity 与 Fragment 中如何使用 Lifecycle 的
上面说到 LifecycleOwner 去设置生命周期的话是调用 LifecycleRegistry.handleLifecycleEvent() 方法,所以要想知道 Activity 和 Fragment 中如何去设置生命周期,其实看看源码,看看它们何时调用这个方法,也很容易找到,这里简单提一下吧。Activity 的话是由 ComponentActivity 实现了 LifecycleOwner 接口,也创建了 LifecycleRegistry 对象,但是它没有直接去操作该对象,在 ComponentActivity 的 onCreate() 中,创建了一个无界面的 ReportFragment,顾名思义,这个 Fragment 是用来上报状态的。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSavedStateRegistryController.performRestore(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
if (mContentLayoutId != 0) {
setContentView(mContentLayoutId);
}
}
Activity 的生命周期分发就是在 ReportFragment 中完成的,这里就不贴代码了,ReportFragment 会在各生命周期调用 dispatch() 方法去分发生命周期事件。
Fragment 直接实现了 LifecycleOwner 接口,但是它也不是自己直接调用,而是由 FragmentManagerImpl 来管理,这个类比较复杂,一两句说不清,限于篇幅就不展开说了,最开始的触发点是 FragmentTransaction 的 commit,有兴趣的可以往下追一下。
六、总结
Lifecycle 应该算是 Jetpack 中比较简单的一个组件,实现和使用都比较简单,也不太会存在需要自定义场景,但是它对我们减少内存泄漏却有很大帮助。