class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycle.addObserver(MainObserver())
}
}
class MainObserver : LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun create(){
logEE(“create”)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun start(){
logEE(“start”)
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun resume(){
logEE(“resume”)
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun pause(){
logEE(“pause”)
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun stop(){
logEE(“stop”)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun destroy(){
logEE(“destroy”)
}
@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
fun any(){
logEE(“any”)
}
}
运行后我们执行如下流程: 启动app-点击回退键退出app,查看生命周期日志打印:
效果展示
我们发现所有的生命周期回调都被调用了,并且每个生命周期调用后都会马上同步调用ON_ANY注解的方法
使用LifeCycle处理异常状态
异常状态说明
我所说的异常状态需要举一个例子:
比如我们现在启动了一个耗时任务去请求网络,然后当网络请求完成后要回来更新ui,我们的异常状态就是指网络请求完成前我们主动关闭了activity。正常情况下这个时候就会造成内存泄露,再次更新ui明显是一个异常状态。本例中我们就需要使用LifeCycle解决此类异常状态。
用到的方法
lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)
测试案例说明和实现
案例说明:
在注册观察者的onCreate方法监听中使用Thread.sleep模拟一个4s耗时任务,然后在Activity中监听任务的回调并打印日志。我们需要模拟两种操作:
- 不关闭页面等待耗时任务完成,耗时任务结束后查看日志
- 在耗时任务结束前关闭页面,耗时任务结束后查看日志
代码展示
注册监听的观察者代码:
lifecycle.addObserver(MainObserver {
runOnUiThread {
if(lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)){
tv.text=“耗时任务完成”
logEE(“耗时任务完成,并成功更新ui”)
}else{
logEE(“生命周期状态不匹配,不能更新ui”)
}
}
})
处理耗时任务的代码:
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun create(){
thread {
Thread.sleep(4000)
fun0()
}
}
两种情况对应的日志
不关闭页面等待耗时任务完成,耗时任务结束后查看日志:
在耗时任务结束前关闭页面,耗时任务结束后查看日志
结论
是使用LifeCycle的lifecycle.currentState.isAtLeast(Lifecycle.State.CREATED)方法可以判断Activity当前的状态,从而灵活的处理异常状态
LifeCycle实现原理
基本原理
先大概的说一下基本的原理:
我们的AppComponentActivity和FragmentActivity都是继承了ComponentActivity。
ComponentActivity实现了LifecycleOwner接口。
在ComponentActivity的onCreate生命周期回调中会添加一个Fragment
所以我们就是借助Fragment来实现生命周期的观察的
这种实现原理机制并不少见,例如Glide、RxPremission都是用的这种方式实现
我总体上把代码讲解分为了下面四个部分
-
ComponentActivity中注册Fragment
-
addObserver添加监听者方法讲解
-
Fragment中生命周期方法联动回调
-
如何回调注解方法
看完后把这四部分相关结合起来理解,就能彻底搞懂LifeCycle源码了
对四部分代码进行讲解
ComponentActivity中注册Fragment
- 注入Fragment
AppComponentActivity
ReportFragment.injectIfNeededIn(this);
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
// Hopefully, we are the first to make a transaction.
manager.executePendingTransactions();
}
这里主要负责把Fragment添加到activity中
addObserver方法讲解
- 方法调用
这个方法会调用到LifecycleRegistry的addObserver
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter–;
}
首先会创建ObserverWithState对象,用来记录生命周期状态,
State targetState = calculateTargetState(observer);
方法会计算出此时的生命周期状态,
后面是一个while循环,while循环会分发生命周期状态
比如你在onResume中进行注册其实也是可以收到onCreate和onStart的注册回调的,这种注册方式实际上就是粘性注册,安卓系统中电量信息的广播接受者就是一种很好的粘性广播注册案例,与这个粘性注册原理相同
后面代码中的方法调用如下
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
isReentrance为false的条件是,当前没有在moveToState方法中分发消息,或者注册者的数量不等于0。如果满足这个条件就会调用sync()方法分发消息
Fragment中生命周期方法联动回调
- ReportFragment中生命周期方法回调
例如:
dispatch(Lifecycle.Event.ON_DESTROY);
private void dispatch(Lifecycle.Event event) {
Activity activity = getActivity();
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
代码中会把Fragment中的所有生命周期回调都调用dispatch方法进行分发,dispatch方法中会调用lifecycle的handleLifecycleEvent方法继续分发
- 跳到LifecycleRegistry类中,找到handleLifecycleEvent方法
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
getStateAfter方法主要用来确认事件触发时下一个生命周期的状态,有下面三种:
CREATED、STARTED、DESTROYED
moveToState方法更改生命周期状态并分发,代码如下:
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;
}
moveToState中的sync()方法用来分发生命周期事件到Observer,
- 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);
}
Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
下面代码是State的几种状态
public enum State {
DESTROYED,
INITIALIZED,
CREATED,
STARTED,
RESUMED;
}
sync方法的while循环中有如下代码:
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
资源分享
- 最新大厂面试专题
这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等
- 对应导图的Android高级工程师进阶系统学习视频
最近热门的,NDK,热修复,MVVM,源码等一系列系统学习视频都有!
est().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
资源分享
- 最新大厂面试专题
这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等
[外链图片转存中…(img-TDzOxJtW-1725877891232)]
- 对应导图的Android高级工程师进阶系统学习视频
最近热门的,NDK,热修复,MVVM,源码等一系列系统学习视频都有!
[外链图片转存中…(img-iSMMa5c1-1725877891233)]