当前位置: 首页 > news >正文

彻底掌握Android中的Lifecycle

彻底掌握Android中的Lifecycle

Lifecycle 是一个生命周期感知型组件,属于 Jetpack 组件库中的一部分,其核心功能是将组件(如Activity 和 Fragment)的生命周期状态通知给观察者(LifecycleObserver)。观察者可以根据这些状态变化来执行相应的操作,如初始化资源、释放资源、更新数据等。通过使用 Lifecycle,开发者可以避免将业务代码和组件强关联,从而提高代码的可读性和可复用性。

Lifecycle使用方式

Lifecycle 的使用方式非常简单,通过 LifecycleOwner 获取 Lifecycle 对象,并添加生命周期观察者就可以了。ComponentActivity 和 Fragment 都默认实现了 LifecycleOwner ,以 Activity 为例,使用方式如下:

class LifecycleActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_lifecycle)//方式一:添加观察者(推荐)lifecycle.addObserver(object : DefaultLifecycleObserver {override fun onCreate(owner: LifecycleOwner) {//doAction...}})//方式二:添加观察者lifecycle.addObserver(object : LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)fun onCreate() {//doAction...}})//方式三:添加观察者lifecycle.addObserver(object : LifecycleEventObserver {override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {when (event) {Lifecycle.Event.ON_CREATE -> {//doAction...}}}})}
}

推荐使用方式一添加观察者,也就是 DefaultLifecycleObserver 类型,使用更方便;方式二已被标为废弃;方式三同样不推荐,是在源码内部使用的。

举个例子,项目中需要埋点页面的停留时间,在页面可见的时候开始算起,页面不可见的时候(退出页面,切换到后台等)上报,通过 Lifecycle 就可以很优雅的实现:

/*** 定义观察者,实现onResume和onStop方法,进行页面停留时间埋点逻辑*/
class ExposureTimeObserver(val pageName: String): DefaultLifecycleObserver {private var start = 0Loverride fun onResume(owner: LifecycleOwner) {start = System.currentTimeMillis()}override fun onStop(owner: LifecycleOwner) {val time = System.currentTimeMillis() - startif (time > 0) {ReportUtil.report("exposureTime", mapOf("pageName" to pageName, "time" to time))}start = 0L}
}//使用时:
页面A:lifecycle.addObserver(ExposureTimeObserver("PageA"))
页面B:lifecycle.addObserver(ExposureTimeObserver("PageB"))

具体业务实现代码都封装在观察者中,Activity 只需注册观察者即可,将业务代码和组件间解耦,提高了代码复用性和可读性。

Lifecycle 的作用:

  1. 简化生命周期回调:避免在应用组件中手动实现繁琐的生命周期回调。
  2. 灵活性:可以与其他 Jetpack 组件(如ViewModel、LiveData等)结合使用,提供更灵活的生命周期管理方案。
  3. 生命周期安全性:确保在正确的生命周期状态下执行相应的操作,避免崩溃或内存泄漏。

Lifecycle 可以说是生命周期的抽象层,统一了各个组件如 Activity、Fragment 的生命周期,让业务代码可以和组件进行解耦,在编写代码时,只需考虑 Lifecycle 抽象出的生命周期方法,而不必关注组件具体的生命周期实现,从而写出更有条理且更精简的代码,更易于维护。通过理解和使用 Lifecycle,可以编写出更加健壮、可维护的代码,并提升应用的性能和用户体验。

Activity 和 Fragment 生命周期:
在这里插入图片描述

Lifecycle 提供的抽象层生命周期:

  • onCreate
  • onStart
  • onResume
  • onPause
  • onStop
  • onDestroy

对应 Lifecycle 状态机的七个事件,Lifecycle 更侧重状态机的事件,而非状态(下面也会有所体现)。

Lifecyle源码解析

Lifecycle 整体实现就是状态机 + 观察者模式,通过空白 Fragment 触发生命周期事件,驱动状态的转移,并通知对应的观察者,这就是 Lifecycle 的工作流程。下面是 Lifecycle 工作时,状态流转的流程图:
在这里插入图片描述

状态机状态流转表如下,可以结合上面的流程图来看。

状态/事件ON_CREATEON_STARTON_RESUMEON_PAUSEON_STOPON_DESTROY
DESTROYED
INITIALIZED
CREATED
STARTED
RESUMED

蓝色是状态,定义了组件在其生命周期中的不同阶段,共五种:

  • INITIALIZED:初始化状态,onCreate被调用之前。
  • CREATED:创建状态,onCreate 或 onStop 调用后。
  • STARTED:启动状态,onStart 或 onPause 调用后。
  • RESUMED:可见状态,onResume调用后。
  • DESTROYED:销毁状态,onDestroy 调用后。

红色是事件,共七种(ANY先忽略):

  • ON_CREATE:对应 onCreate 方法。
  • ON_START:对应 onStart 方法。
  • ON_RESUME:对应 onResume 方法。
  • ON_PAUSE:对应 onPause 方法。
  • ON_STOP:对应 onStop 方法。
  • ON_DESTROY:对应 onDestroy 方法。
  • ON_ANY:匹配任何事件。

下面看一下 Lifecycle 的源码的具体实现,类间关系图如下:
在这里插入图片描述
Lifecycle 发挥作用的类主要有以下几个:

  • LifecycleOwner:表示一个具有生命周期的组件,只有 getLifecycle 方法,可以调用该方法拿到 Lifecycle 来添加生命周期观察者,Activity 和 Fragment 都实现了 LifecycleOwner 接口。

    //接口定义
    public interface LifecycleOwner {public val lifecycle: Lifecycle
    }//Activity中:
    public class ComponentActivity extends ComponentActivity implements LifecycleOwner,... {//可见真正干活的是 LifecycleRegistryprivate final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);public Lifecycle getLifecycle() {return mLifecycleRegistry;}
    }
    
  • ReportFragment:负责监听生命周期的变动,并产生对应的事件来驱动 Lifecycle 的状态改变。这里的实现在不同 Android SDK 版本上略有区别:API 大于等于 29,是通过 Activity.registerActivityLifecycleCallbacks 方法监听生命周期;API 小于 29,则是通过 ReportFragment 自身生命周期来驱动的。

    在 ComponentActivity 的 onCreate 方法中会进行 ReportFragment 的注入,源码:

    class ComponentActivity {...protected void onCreate(Bundle savedInstanceState) {...ReportFragment.injectIfNeededIn(this);}...
    }
    
    open class ReportFragment() : android.app.Fragment() {companion object {private const val REPORT_FRAGMENT_TAG ="androidx.lifecycle.LifecycleDispatcher.report_fragment_tag"@JvmStaticfun injectIfNeededIn(activity: Activity) {//1.注入Fragment,区分SDK版本做具体实现if (Build.VERSION.SDK_INT >= 29) {// On API 29+, we can register for the correct Lifecycle callbacks directlyLifecycleCallbacks.registerIn(activity)}val manager = activity.fragmentManagerif (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {manager.beginTransaction().add(ReportFragment(), REPORT_FRAGMENT_TAG).commit()// Hopefully, we are the first to make a transaction.manager.executePendingTransactions()}}}override fun onActivityCreated(savedInstanceState: Bundle?) {super.onActivityCreated(savedInstanceState)dispatchCreate(processListener)dispatch(Lifecycle.Event.ON_CREATE)}override fun onStart() {super.onStart()dispatchStart(processListener)dispatch(Lifecycle.Event.ON_START)}...private fun dispatch(event: Lifecycle.Event) {//2.API小于29走这里if (Build.VERSION.SDK_INT < 29) {dispatch(activity, event)}}@RequiresApi(29)internal class LifecycleCallbacks : Application.ActivityLifecycleCallbacks {override fun onActivityPostCreated(activity: Activity,savedInstanceState: Bundle?) {//3.API大于等于29走这里dispatch(activity, Lifecycle.Event.ON_CREATE)}override fun onActivityPostStarted(activity: Activity) {dispatch(activity, Lifecycle.Event.ON_START)}...companion object {@JvmStaticfun registerIn(activity: Activity) {activity.registerActivityLifecycleCallbacks(LifecycleCallbacks())}}}
    }
    
  • Lifecycle:是一个抽象类, 定义了添加和移除观察者的抽象方法,实现了协程作用域的管理。还定义了有框架中用到的状态(State)和事件(Event),也有通过状态推导出事件等方法。

    public abstract class Lifecycle {//1.协程作用域的存储@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)public var internalScopeRef: AtomicReference<Any> = AtomicReference<Any>()//2.观察者的添加和移除public abstract fun addObserver(observer: LifecycleObserver)public abstract fun removeObserver(observer: LifecycleObserver)//3.记录当前状态public abstract val currentState: State//4.事件public enum class Event {ON_CREATE,ON_START,ON_RESUME,ON_PAUSE,ON_STOP,ON_DESTROY,ON_ANY;//5.根据事件推导出下一状态public val targetState: Stateget() {when (this) {ON_CREATE, ON_STOP -> return State.CREATEDON_START, ON_PAUSE -> return State.STARTEDON_RESUME -> return State.RESUMEDON_DESTROY -> return State.DESTROYEDON_ANY -> {}}throw IllegalArgumentException("$this has no target state")}//6.根据状态推导出驱动的事件(down和up代表不同的方向,可参考上面的流程图)public companion object {@JvmStaticpublic fun downFrom(state: State): Event? {return when (state) {State.CREATED -> ON_DESTROYState.STARTED -> ON_STOPState.RESUMED -> ON_PAUSEelse -> null}}@JvmStaticpublic fun downTo(state: State): Event? {return when (state) {State.DESTROYED -> ON_DESTROYState.CREATED -> ON_STOPState.STARTED -> ON_PAUSEelse -> null}}@JvmStaticpublic fun upFrom(state: State): Event? {return when (state) {State.INITIALIZED -> ON_CREATEState.CREATED -> ON_STARTState.STARTED -> ON_RESUMEelse -> null}}@JvmStaticpublic fun upTo(state: State): Event? {return when (state) {State.CREATED -> ON_CREATEState.STARTED -> ON_STARTState.RESUMED -> ON_RESUMEelse -> null}}}}public enum class State {DESTROYED,INITIALIZED,CREATED,STARTED,RESUMED;}
    }//...协程作用域相关的方法...
    

    1.存储协程作用域对象,获取时才会创建。创建时通过 while 循环 + CAS 机制保证线程安全。

    2.只定义了添加和移除观察者抽象方法,具体的观察者管理由 LifecycleRegistry 负责。

    3.当前状态,与组件生命周期同步

    5.根据生命周期触发的事件,得到事件触发后的目标状态

    6.downFrom、downTo、upFrom、upTo 四个方法,xxFrom 系列返回当前状态转换到下一状态的响应事件;xxTo 系列返回流转到当前状态的驱动事件。down 和 up 表示不同方向,up 表示从前向后的流转,down 则相反。

  • LifecycleRegistry,该类是 Lifecycle 抽象类的唯一实现,同时也是框架的核心,其内不仅维护着所有观察者和对应状态,同时也会收到驱动事件,同步状态变更,并调用对应观察者的回调方法。

    open class LifecycleRegistry private constructor(provider: LifecycleOwner,private val enforceMainThread: Boolean
    ) : Lifecycle() {//1.存储所有观察者和对应状态private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =new FastSafeIterableMap<>();//2.组件当前状态,默认是INITIALIZEDprivate var state: State = State.INITIALIZED//3.处理生命周期变动事件open fun handleLifecycleEvent(event: Event) {...}//...4.具体的同步代码,包括moveToState、sync、backwardPass、forwardPass等方法...//5.添加和移除观察者具体实现override fun addObserver(observer: LifecycleObserver) {...}override fun removeObserver(observer: LifecycleObserver) {...}
    }
    

    1.FastSafeIterableMap 相当于把 SafeIterableMap 再封装了一层,SafeIterableMap存储的是<K,V>,则它是存储的<K,<K,V>。该类型是用链表实现的,模拟成 Map 接口,特性是支持在遍历的时候删除元素,非线程安全。

    2.handleLifecycleEvent是状态同步的入口,ReportFragment 发出生命周期变更的事件后,最终会调用到该方法,由此开始,进行观察者状态同步和触发方法回调。

    open fun handleLifecycleEvent(event: Event) {enforceMainThreadIfNeeded("handleLifecycleEvent")//1.获取事件触发后的目标状态,可以结合上图来看,源码在Lifecycle的targetState。//2.调用moveToState开始同步观察者状态moveToState(event.targetState)
    }
    
    private fun moveToState(next: State) {if (state == next) {return}check(!(state == State.INITIALIZED && next == State.DESTROYED)) {"no event down from $state in component ${lifecycleOwner.get()}"}//1.将Lifecycle当前状态修改为目标状态state = nextif (handlingEvent || addingObserverCounter != 0) {newEventOccurred = true// we will figure out what to do on upper level.return}handlingEvent = true//2.同步观察者的状态,并触发对应回调sync()handlingEvent = false//3.如果目标状态为Destroy,清空观察者if (state == State.DESTROYED) {observerMap = FastSafeIterableMap()}
    }
    

    moveToState方法主要做了三件事:

    1. 将 LifecycleRegistry 当前状态更改为目标状态,该状态是页面的真实状态,每个观察者也包含自己的状态
    2. 调用 sync() 方法,主要是让观察者自己的状态和 LifecycleRegistry 的状态进行对齐
    3. 如果目标状态是Destory,则清空所有观察者

    下面继续看 sync() 方法:

    private fun sync() {val lifecycleOwner = lifecycleOwner.get()?: throw IllegalStateException("LifecycleOwner of this LifecycleRegistry is already " +"garbage collected. It is too late to change lifecycle state.")//1.状态不同步则进行状态对齐操作while (!isSynced) {newEventOccurred = false//2.具体的同步方法if (state < observerMap.eldest()!!.value.state) {backwardPass(lifecycleOwner)}val newest = observerMap.newest()if (!newEventOccurred && newest != null && state > newest.value.state) {forwardPass(lifecycleOwner)}}newEventOccurred = false
    }//新添加的观察、最早添加的观察者和Lifecycle的状态相同才会返回false,保证map中所有观察者状态同步
    private val isSynced: Booleanget() {if (observerMap.size() == 0) {return true}val eldestObserverState = observerMap.eldest()!!.value.state  //返回链表第一个,最早添加的元素val newestObserverState = observerMap.newest()!!.value.state  //返回链表最后一个,最新添加的元素return eldestObserverState == newestObserverState && state == newestObserverState}
    

    该方法主要做的事就是状态对齐,让 LifecycleRegistry 状态和每个观察者自身的状态同步到一致,并在同步过程中调用观察者回调方法。

    具体做法是先**从后往前(backwardPass)同步,然后再从前往后(forwardPass)**同步,可以对照开头的 Lifecycle 时序图,状态由 INITIALIZED -> RESUMED 是从前向后,反之就是从后向前。

    两个方向的代码实现差不多,这里就从后向前以为例:

    private fun backwardPass(lifecycleOwner: LifecycleOwner) {val descendingIterator = observerMap.descendingIterator()//1.遍历所有观察者while (descendingIterator.hasNext() && !newEventOccurred) {val (key, observer) = descendingIterator.next()//2.判断观察者状态和当前状态,逐步进行同步while (observer.state > state && !newEventOccurred && observerMap.contains(key)) {//3.具体的同步操作val event = Event.downFrom(observer.state)?: throw IllegalStateException("no event down from ${observer.state}")pushParentState(event.targetState)observer.dispatchEvent(lifecycleOwner, event)popParentState()}}
    }
    

    可以看到,该方法会遍历所有观察者,同步每个观察者的状态,并调用观察者对应的生命周期方法。

    1.遍历所有观察者,同步每个观察者的状态

    2.判断观察者状态是否大于最新状态,符合条件则进入 while 循环进行同步操作。(大于判断是因为这里只关注从后向前的同步)

    3.找到观察者状态切换的下一个事件,根据事件调用观察者回调方法,并更新观察者状态。

    举个例子,当进入第 2 步的时候,观察者 A 的状态是 RESUMED,而最新状态是 CREATED,此时进入第 3 步。首先通过 downFrom 找出流转到下一状态的事件(downFrom 是从后向前),也就是 ON_PAUSE,然后通过观察者的 dispatchEvent 方法分发:

    fun dispatchEvent(owner: LifecycleOwner?, event: Event) {val newState = event.targetStatestate = min(state, newState)lifecycleObserver.onStateChanged(owner!!, event)state = newState
    }
    

    dispatchEvent 方法中会回调 onPause 方法,并将状态更新为 STARTED。再回到第 2 步,STATED 仍然大于 CREATED,再进入第三步:找出 ON_STOP 事件,回调 onStop 方法,观察者状态同步为 CREATED,此时观察者 A 状态和最新状态保持一致了,这就是状态同步的流程。

    注意:枚举如果没定义值,则默认是根据定义的位置来决定的

    通过上面流程可以发现,状态的同步是按次序的,不能跨状态同步,可以参考上面的时序图,并不能将状态直接一步对齐成最新的状态,因为 Lifecycle 侧重事件的回调,从一个状态到另一个状态,需要找出所有导致状态变更的事件,并执行对应观察者方法。

    添加新的观察者时也有相同的对齐逻辑:

    override fun addObserver(observer: LifecycleObserver) {enforceMainThreadIfNeeded("addObserver")val initialState = if (state == State.DESTROYED) State.DESTROYED else State.INITIALIZEDval statefulObserver = ObserverWithState(observer, initialState)val previous = observerMap.putIfAbsent(observer, statefulObserver)if (previous != null) {return}val lifecycleOwner = lifecycleOwner.get()?: // it is null we should be destroyed. Fallback quicklyreturnval isReentrance = addingObserverCounter != 0 || handlingEventvar targetState = calculateTargetState(observer)addingObserverCounter++while (statefulObserver.state < targetState && observerMap.contains(observer)) {pushParentState(statefulObserver.state)val event = Event.upFrom(statefulObserver.state)?: throw IllegalStateException("no event up from ${statefulObserver.state}")statefulObserver.dispatchEvent(lifecycleOwner, event)popParentState()// mState / subling may have been changed recalculatetargetState = calculateTargetState(observer)}if (!isReentrance) {// we do sync only on the top level.sync()}addingObserverCounter--
    }
    

    添加新的观察者一般情况默认是 INITIALIZED 状态,所以同样需要同步到最新状态。举个例子,在页面 onResume 时添加观察者,此时将观察者的回调方法都打印一下:
    在这里插入图片描述
    新添加的观察者依次调用了 onCreate、onStart 和 onResume 回调。说明 Lifecycle 侧重状态机的事件,从一个状态到另一个状态,需要找出所有导致状态变更的事件,并执行对应观察者方法,不能将某个事件漏掉,以免调用时代码出错。

    状态观察者:外部添加的观察者内部会包装一层,目的是保存观察者状态,方便和最新状态做对比。

    internal class ObserverWithState(observer: LifecycleObserver?, initialState: State) {var state: Statevar lifecycleObserver: LifecycleEventObserverinit {lifecycleObserver = Lifecycling.lifecycleEventObserver(observer!!)state = initialState}fun dispatchEvent(owner: LifecycleOwner?, event: Event) {val newState = event.targetStatestate = min(state, newState)lifecycleObserver.onStateChanged(owner!!, event)state = newState}
    }
    
  • LifecycleObserver:表示一个可以观察 LifecycleOwner 生命周期状态的组件。开发人员可以通过重写 DefaultLifecycleObserver 接口来监听 LifecycleOwner 的生命周期状态变化,并实现对应逻辑。

    public interface DefaultLifecycleObserver : LifecycleObserver {public fun onCreate(owner: LifecycleOwner) {}public fun onStart(owner: LifecycleOwner) {}public fun onResume(owner: LifecycleOwner) {}public fun onPause(owner: LifecycleOwner) {}public fun onStop(owner: LifecycleOwner) {}public fun onDestroy(owner: LifecycleOwner) {}
    }
    

    之所以可以直接使用 DefaultLifecycleObserver,是因为源码内部还通过适配器模式进行了版本兼容,这也是适配器模式的经典用法。源码如下:

    internal class DefaultLifecycleObserverAdapter(private val defaultLifecycleObserver: DefaultLifecycleObserver,private val lifecycleEventObserver: LifecycleEventObserver?
    ) : LifecycleEventObserver {override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {when (event) {Lifecycle.Event.ON_CREATE -> defaultLifecycleObserver.onCreate(source)Lifecycle.Event.ON_START -> defaultLifecycleObserver.onStart(source)Lifecycle.Event.ON_RESUME -> defaultLifecycleObserver.onResume(source)Lifecycle.Event.ON_PAUSE -> defaultLifecycleObserver.onPause(source)Lifecycle.Event.ON_STOP -> defaultLifecycleObserver.onStop(source)Lifecycle.Event.ON_DESTROY -> defaultLifecycleObserver.onDestroy(source)Lifecycle.Event.ON_ANY ->throw IllegalArgumentException("ON_ANY must not been send by anybody")}lifecycleEventObserver?.onStateChanged(source, event)}
    }
    

为什么State不是设置为7种呢

Lifecycle 中有两个很奇怪的状态,分别是 CREATED 和 STARTED,先说 CREATED 状态,通过 ON_CREATE 事件转换为 CREATED 状态可以理解,但通过 CREATED 事件也转换为 CREATED 似乎有些不合常理;STARTED 状态也是一样,为什么 Google 工程师没有再新建两个 STOPED 和 PAUSED 状态呢?个人认为 Lifecycle 侧重的是事件而非状态,CREATED 或 STOPED 状态对于上层来说区别不大,Lifecycle 比较关注的状态可能只有已经定义的五个了。其次复用这两种状态,少了两个枚举,更节省内存。缺点就是代码复杂些,就上述流程图来说,状态的流转并不是单向的了,而是双向的,这就需要根据旧状态和新状态判断方向,从而推断出驱动状态转换的事件,继而调用对应的生命周期方法回调。如此非常巧妙的设计,让人叹为观止。

总结

Lifecycle 是状态机 + 观察者模式的结合,通过 ReportFragment 触发事件,驱动 LifecycleRegistry 中所有观察者状态同步,并根据同步结果触发观察者对应的回调方法,这就是它的整体原理。

Lifecycle 虽然只是提供了抽象层的组件生命周期监听,但这一改变可以让软件编码灵活性大大加强,LiveData 就是基于 Lifecycle 来实现的。通过使用 Lifecycle,可以编写出更加健壮、可维护的代码,提升应用的性能和用户体验。

空白 Fragment 监听生命周期的方式也有很多优秀的三方库在用,比如 Glide,通过这种方式来监听生命周期,处理图片的加载和回收。一些动态权限处理三方库,通过添加空白 Fragment 来监听权限请求结果,从而简化调用处代码,优秀的思路都是相通的。

参考

官方文档:Lifecycle
状态机:重修设计模式-行为型-状态模式
观察者模式:重修设计模式-行为型-观察者模式


http://www.mrgr.cn/news/50207.html

相关文章:

  • mysql锁之乐观锁、悲观锁、表锁、行锁、共享锁、排他锁
  • Apache Kafka消息传递策略
  • P2P 网络 简单研究 1
  • ja-netfilter-all
  • 【Oracle 数据库技术分享】BLOB 与 CLOB 的选择与应用
  • 530 Login fail. A secure connection is requiered(such as ssl)
  • 外包干了3个月,技术退步明显
  • CesiumJS 案例 P1:创建 Viewer、通过 JS API 隐藏控件、通过 CSS 隐藏控件、隐藏元素
  • 力扣题解(鸡蛋掉落)
  • Apache Kafka各Api模块说明
  • 学习底座架构-武汉
  • [0xGame 2024] week1
  • 进程相关及守护进程
  • 电脑显示d3dcompiler_47.dll缺失如何修复,马上教你6个修复方法
  • Windows环境下安装使用curl命令
  • 【从零开始的LeetCode-算法】2135. 统计追加字母可以获得的单词数
  • Linux——Harbor(容器镜像 管理项目)
  • c语言字符函数
  • 力扣随机题
  • Django模型优化