LifeCycle
前言
Hello大家好,这里是BlueLzy。本文是JetPack全家桶系列文章的第一篇。作为一名Android开发者,在2021年必备的技能之一就是熟练使用Google为我们提供的开发组件,这一套组件的名字就是:JetPack。里面包括了许多不同功能的SDK,Google推出这套开发组件的目的就是为了能够让开发者在遵循Android系统的生命周期的同时,写出Bug更少,代码量更少,性能更好的App。
因此,这一系列文章会按照下面的顺序来介绍其中几个最主要的组件,在学习完这些基本组件之后,通过一个小项目在实践中学习API的时候,领会SDK的设计思想和原理等等。达到学以致用的目的。
下面是系列文章的目录:
- Lifecycle - 生命周期感知型组件
- LiveData - 可观察的数据存储器类
- ViewModel - 结合LiveData和LifeCycle的数据管理组件
- DataBinding - 声明式数据驱动UI组件
除了上面介绍了这几个组件,JetPack其实还提供了其他许多组件,包括:WorkManager,Navigation,Paging等等
我们可以通过Google的官方网站进行查阅:
本文目录
什么是Lifecycle
一般来说,无论是Github上优秀的开源库,还是Google推出的新技术,都是为了解决旧的技术遗留的历史问题,也就是说,我们在学习新技术的时候,不仅要学会如何使用API,还要思考“为什么要有这个技术?”,“它和之前的解决方案相比,有什么优势?”
当然,要知道“Why”,首先还是要知道“What”和“How”。知其然,知其所以然。
远古时代
在Android开发中,我们需要遵循组件的生命周期,例如在**onStart()和onResume()的时候更新UI,在onStop()和onDestroy()**的时候停止后台任务和释放资源。
举个常见的例子:我们需要在Activity的生命周期到底onCreate()的时候调用接口请求数据,然后在onResume()的时候设置到UI界面中,并且在onStop()的时候停止请求,否则有可能会出现内存泄漏的情况。
class MyActivity : AppCompatActivity() {
private lateinit var request: MainRequset
private var data: List<String> = mutableListOf()
override fun onCreate(...) {
request= MainRequset(this) { list ->
// update UI
data = list
}
}
public override fun onResume() {
super.onStart()
textView.setText(data[0])
}
public override fun onStop() {
super.onStop()
request.stop()
}
}
随着项目不断迭代,需要在生命周期的不同阶段做的任务也越来越多,导致了这几个生命周期方法里面的业务代码越来越臃肿,最后接手的开发者难以维护。
class MyActivity : AppCompatActivity() {
private lateinit var request: MainRequest // 首页数据
private lateinit var firebase: FireBase // 性能监控
private lateinit var pushNotification: PushNotification // 推送服务
private lateinit var startup: SplashScreen // 开屏广告
private var data: List<String> = mutableListOf()
override fun onCreate(...) {
request = MainRequest(this) { list ->
// update UI
data = list
}
firebase = FireBase(this) { isSucceed ->
// do Something
}
pushNotification = PushNotification(this) { isSucceed->
// do Something
}
startup = SplashScreen(this) { isSucceed->
// do Something
}
}
public override fun onResume() {
super.onStart()
textView.setText(data[0])
//...
}
public override fun onStop() {
super.onStop()
request.stop()
firebase.stop()
pushNotification.stop()
startup.stop()
}
}
Lifecycle的出现
这里我们引用Google Developers的图来说明Lifecycle的工作流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f7Xx7UtM-1634372149308)(LifeCycle%2009b61eb62a684bc8a52e4d402f0e7ff4/Untitled.png)]
我们可以通过在代码使用LifecycleObserver和@OnLifecycleEvent注解来实现对生命周期回调方法的监听。举个例子:
class MainActivity : BaseDataBindingActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
applyExitMaterialTransform()
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(testListener())
}
inner class testListener(): LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start() {
Log.d("bluelzy", "start")
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop() {
Log.d("bluelzy","stop")
}
}
}
上面这段代码主要做了两件事:
- 定义了一个testListener内部类,它继承自LifecycleObserver接口,并且定义了两个方法,分别在onStart()和onStop()的时候会接收到回调
- 在Activity的onCreate()中通过addObserver()方法把testListener添加到观察者列表中
然后运行程序,我们可以看到Logcat中会打印出来,当MainActivity的生命周期到onStart()的时候,会调用testListener的start()方法,同样当生命周期到了onStop()的时候,会调用testListener的stop()方法。
相比起之前我们在Activity的各个生命周期方法中写一大段业务代码,是不是简化了许多?
在这里我们会有一些疑问:
- LifecycleObserver 是什么,观察者模式是什么运作的?
- Lifecycle原理是什么?为什么调用addOberver就可以观察到对应组件的生命周期了?
这些疑问需要我们从源码来解答。
Lifecycle的原理和设计思想
上面我们提出了两个问题,就是关于Lifecycle是如何运作的,它背后的原理到底是什么?我们通过源码来一步步解析。
首先Lifecycle有几个关键的类,分别是:
- Lifecycle:抽象类,唯一子类就是LifecycleRegistry
- LifecycleOwner:具有生命周期感知能力的类需要实现的接口
- LifecycleOberver:Lifecycle需要观察的对象们(被观察者)
- LifecycleRegistry:负责转发生命周期事件,Lifecycle的真正的实现类
接下来我们一个个来详细讲解。
Abstract Class: Lifecycle
Lifecycle所在路径:package androidx.lifecycle;
整个Lifecycle类再2.2.0版本只有200行代码,主要是定义了生命周期相关状态,以及Observer相关的add和remove方法。
下面是Lifecycle.java源码
public abstract class Lifecycle {
/**
* Lifecycle coroutines extensions stashes the CoroutineScope into this field.
*
* @hide used by lifecycle-common-ktx
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
@NonNull
AtomicReference<Object> mInternalScopeRef = new AtomicReference<>();
/**
* Adds a LifecycleObserver that will be notified when the LifecycleOwner changes
* state.
* <p>
* The given observer will be brought to the current state of the LifecycleOwner.
* For example, if the LifecycleOwner is in {@link State#STARTED} state, the given observer
* will receive {@link Event#ON_CREATE}, {@link Event#ON_START} events.
*
* @param observer The observer to notify.
*/
@MainThread
public abstract void addObserver(@NonNull LifecycleObserver observer);
/**
* Removes the given observer from the observers list.
* <p>
* If this method is called while a state change is being dispatched,
* <ul>
* <li>If the given observer has not yet received that event, it will not receive it.
* <li>If the given observer has more than 1 method that observes the currently dispatched
* event and at least one of them received the event, all of them will receive the event and
* the removal will happen afterwards.
* </ul>
*
* @param observer The observer to be removed.
*/
@MainThread
public abstract void removeObserver(@NonNull LifecycleObserver observer);
/**
* Returns the current state of the Lifecycle.
*
* @return The current state of the Lifecycle.
*/
@MainThread
@NonNull
public abstract State getCurrentState();
@SuppressWarnings("WeakerAccess")
public enum Event {
/**
* Constant for onCreate event of the {@link LifecycleOwner}.
*/
ON_CREATE,
/**
* Constant for onStart event of the {@link LifecycleOwner}.
*/
ON_START,
/**
* Constant for onResume event of the {@link LifecycleOwner}.
*/
ON_RESUME,
/**
* Constant for onPause event of the {@link LifecycleOwner}.
*/
ON_PAUSE,
/**
* Constant for onStop event of the {@link LifecycleOwner}.
*/
ON_STOP,
/**
* Constant for onDestroy event of the {@link LifecycleOwner}.
*/
ON_DESTROY,
/**
* An {@link Event Event} constant that can be used to match all events.
*/
ON_ANY
}
/**
* Lifecycle states. You can consider the states as the nodes in a graph and
* {@link Event}s as the edges between these nodes.
*/
@SuppressWarnings("WeakerAccess")
public enum State {
/**
* Destroyed state for a LifecycleOwner. After this event, this Lifecycle will not dispatch
* any more events. For instance, for an {@link android.app.Activity}, this state is reached
* <b>right before</b> Activity's {@link android.app.Activity#onDestroy() onDestroy} call.
*/
DESTROYED,
/**
* Initialized state for a LifecycleOwner. For an {@link android.app.Activity}, this is
* the state when it is constructed but has not received
* {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} yet.
*/
INITIALIZED,
/**
* Created state for a LifecycleOwner. For an {@link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {@link android.app.Activity#onCreate(android.os.Bundle) onCreate} call;
* <li><b>right before</b> {@link android.app.Activity#onStop() onStop} call.
* </ul>
*/
CREATED,
/**
* Started state for a LifecycleOwner. For an {@link android.app.Activity}, this state
* is reached in two cases:
* <ul>
* <li>after {@link android.app.Activity#onStart() onStart} call;
* <li><b>right before</b> {@link android.app.Activity#onPause() onPause} call.
* </ul>
*/
STARTED,
/**
* Resumed state for a LifecycleOwner. For an {@link android.app.Activity}, this state
* is reached after {@link android.app.Activity#onResume() onResume} is called.
*/
RESUMED;
/**
* Compares if this State is greater or equal to the given {@code state}.
*
* @param state State to compare with
* @return true if this State is greater or equal to the given {@code state}
*/
public boolean isAtLeast(@NonNull State state) {
return compareTo(state) >= 0;
}
}
可以看到,主要定义了两个枚举类型,分别为Event和State,这两者都和生命周期方法回调相对应。可以参考上面的图。
举个例子:
Activity的生命周期走了onStart()方法,这时候会触发ON_START事件(Event),并且对应的状态(State)也会变成STARTED。这个状态在LiveData是否进行回调的时候会用到。
Interface: LifecycleObserver
public interface LifecycleObserver {
}
没有任何方法的一个空接口,所有实现了这个接口的类本质上都具有对生命周期的“被”观察能力。它们在生命周期方法回调的时候,在LifecycleRegistry中会进行分发。
Interface: LifecycleOwner
public interface LifecycleOwner {
/**
* Returns the Lifecycle of the provider.
*
* @return The lifecycle of the provider.
*/
@NonNull
Lifecycle getLifecycle();
}
这个类是一个接口,里面只有一个方法,就是getLifecycle(),返回Lifecycle对象。无论是Activity还是Fragment,都实现了这个接口,而他们返回的Lifecycle对象,就是LifecycleRegistry
Class: LifecycleRegistry
接下来看看LifecycleRegistry,它作为Lifecycle唯一的实现类,承载了生命周期分发的职责。
在Lifecycle里面通过addObserver()方法添加的LifecycleObserver,都会进行生命周期分发。
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
new FastSafeIterableMap<>()
@MainThread
public void setCurrentState(@NonNull State state) {
moveToState(state);
}
/**
* Sets the current state and notifies the observers.
* <p>
* Note that if the {@code currentState} is the same state as the last call to this method,
* calling this method has no effect.
*
* @param event The event that was received
*/
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
private void moveToState(State next) {
if (mState == next) {
return;
}
mState = next;
if (mHandlingEvent || mAddingObserverCounter != 0) {
mNewEventOccurred = true;
// we will figure out what to do on upper level.
return;
}
mHandlingEvent = true;
sync();
mHandlingEvent = false;
}
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);
}
主要的方法就是handleLifecycleEvent(),在通过getStateAfter()把Event转为State之后进行分发
在分发之前,还需要做一步操作,
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);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
可以看到,在sync()方法里面,还要判断当前State。
- 如果当前State小于ObserverMap的状态,说明当前生命周期组件状态需要“降级”
- 如果当前State大于ObserverMap的状态,说明当前生命周期组件状态需要“升级”
关于“升级”和“降级”的方法可以看下面代码:
@Nullablepublic 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; }}@Nullablepublic 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; }}
举个例子:当前Activity的生命周期到了onCreate(),然后需要进行生命周期事件分发,这时候生命周期是STARTED,但是mState还是INITIALIZED,因此需要执行forwardPass()。
执行结束之后再进行生命周期事件分发:
private void forwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator = mObserverMap.iteratorWithAdditions(); while (ascendingIterator.hasNext() && !mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next(); ObserverWithState observer = entry.getValue(); while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { pushParentState(observer.mState); observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); } } } 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()))) { Event event = downEvent(observer.mState); pushParentState(getStateAfter(event)); observer.dispatchEvent(lifecycleOwner, event); popParentState(); } }
分发的方法就是:dispatchEvent()
void dispatchEvent(LifecycleOwner owner, Event event) { State newState = event.getTargetState(); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState;}
到这里为止,整个Lifecycle的生命周期分发过程就讲解完了。大家跟着源码读一遍的话思路还是挺清晰的。有什么疑问欢迎评论区随时留言~
下面还从Android Developer官方摘抄了一些最佳实践的提示。
总结
Lifecycle的最佳实践
- 使界面控制器(Activity 和 Fragment)尽可能保持精简。它们不应试图获取自己的数据,而应使用
[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
执行此操作,并观察[LiveData](https://developer.android.com/reference/androidx/lifecycle/LiveData)
对象以将更改体现到视图中。 - 设法编写数据驱动型界面,对于此类界面,界面控制器的责任是随着数据更改而更新视图,或者将用户操作通知给
[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
。 - 将数据逻辑放在
[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
类中。[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
应充当界面控制器与应用其余部分之间的连接器。不过要注意,[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
不负责获取数据(例如,从网络获取)。但是,[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
应调用相应的组件来获取数据,然后将结果提供给界面控制器。 - 使用数据绑定在视图与界面控制器之间维持干净的接口。这样一来,您可以使视图更具声明性,并尽量减少需要在 Activity 和 Fragment 中编写的更新代码。如果您更愿意使用 Java 编程语言执行此操作,请使用诸如 Butter Knife 之类的库,以避免样板代码并实现更好的抽象化。
- 如果界面很复杂,不妨考虑创建 presenter 类来处理界面的修改。这可能是一项艰巨的任务,但这样做可使界面组件更易于测试。
- 避免在
[ViewModel](https://developer.android.com/reference/androidx/lifecycle/ViewModel)
中引用[View](https://developer.android.com/reference/android/view/View)
或[Activity](https://developer.android.com/reference/android/app/Activity)
上下文。如果ViewModel
存在的时间比 activity 更长(在配置更改的情况下),activity 将泄露并且不会得到垃圾回收器的妥善处置。 - 使用 Kotlin 协程管理长时间运行的任务和其他可以异步运行的操作。
Lifecycle的使用场景
Lifecycle可使您在各种情况下更轻松地管理生命周期。下面列举几个例子:
- 在粗粒度和细粒度位置更新之间切换。使用生命周期感知型组件可在位置应用可见时启用细粒度位置更新,并在应用位于后台时切换到粗粒度更新。借助生命周期感知型组件
[LiveData](https://developer.android.com/reference/androidx/lifecycle/LiveData)
,应用可以在用户使用位置发生变化时自动更新界面。 - 停止和开始视频缓冲。使用生命周期感知型组件可尽快开始视频缓冲,但会推迟播放,直到应用完全启动。此外,应用销毁后,您还可以使用生命周期感知型组件终止缓冲。
- 开始和停止网络连接。借助生命周期感知型组件,可在应用位于前台时启用网络数据的实时更新(流式传输),并在应用进入后台时自动暂停。
- 暂停和恢复动画可绘制资源。借助生命周期感知型组件,可在应用位于后台时暂停动画可绘制资源,并在应用位于前台后恢复可绘制资源。