写点什么

android LifeCycle- 简单使用和详细原理解析,2021 大厂 Android 面试经历

用户头像
Android架构
关注
发布于: 1 小时前

使用方法

总的来说 LifeCycle 的使用非常简单,基本没什么好写的,使用方法的章节仅限于绝对新手参考。


说是徒劳的,先上一波简单使用的代码吧

代码展示

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 中监听任务的回调并打印日志。我们需要模拟两种操作:


  1. 不关闭页面等待耗时任务完成,耗时任务结束后查看日志

  2. 在耗时任务结束前关闭页面,耗时任务结束后查看日志



代码展示

注册监听的观察者代码:


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 都是用的这种方式实现


我总体上把代码讲解分为了下面四个部分


  1. ComponentActivity 中注册 Fragment

  2. addObserver 添加监听者方法讲解

  3. Fragment 中生命周期方法联动回调

  4. 如何回调注解方法


看完后把这四部分相关结合起来理解,就能彻底搞懂 LifeCycle 源码了

对四部分代码进行讲解

ComponentActivity 中注册 Fragment

  1. 注入 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 方法讲解

  1. 方法调用


这个方法会调用到 LifecycleRegistry 的 addObserver


@Overridepublic 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 recalculatetargetState = 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 中生命周期方法联动回调

  1. 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 方法继续分发


  1. 跳到 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,


  1. 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);}


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


上面这行代码会比较当前生命周期状态和最早被加入到 SafeIterableMap 中的状态,如果小于零(比如一般第一个被加入的是 INITIALIZED 状态,当前状态比 ONCREATE 还小只能是 DESTROYED 状态了),说明当前生命周期需要被 backwardPass 处理


Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();if (!mNewEventOccurred && newest != null&& mState.compareTo(newest.getValue().mState) > 0) {forwardPass(lifecycleOwner);}


上面代码中 newest 是最新被添加到 mObserverMap 中的状态,如果当前生命周期状态大于 newest 状态,说明状态在前进(比如 onCreate 到 onStart)


  1. 继续看 backwardPass 和 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);

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
android LifeCycle-简单使用和详细原理解析,2021大厂Android面试经历