Android Jetpact Lifecycle 解析

认识 Lifecycle

Lifecycle 是什么

LifecycleJetpack 组件库中的一个生命周期感知型组件。在 Lifecycle 出现之前,需要手动从外部宿主(如 Activity、Fragment 或自定义宿主)中将生命周期事件分发到功能组件内部,这势必会造成宿主代码复杂度增加。有了 Lifecycle 的存在,搭建依赖于生命周期变化的业务逻辑变得简单高效,可以用一种统一的方式来监听 Activity、Fragment、甚至是 Process 的生命周期变化,且大大减少了业务代码发生内存泄漏的风险。

事件和状态

Lifecycle 中定义了7种生命周期事件:

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

和 5 种生命周期状态:

  • INITIALIZED: Lifecycle 初始化完成,且还未收到 onCreate() 事件时的状态。
  • CREATED:onCreate() 调用之后,或者onStop() 调用之后的状态。
  • STARTED:onStart() 调用之后,或者onPause() 调用之后的状态。
  • RESUMED:onResume() 调用之后,onPause() 调用之前的状态。
  • DESTROYED:onDestory() 调用之后的状态。

事件和状态之间的关系如下图所示,这也是 Lifecycle 分发生命周期状态的流程(记住这张图,后面要考的):
Lifecycle生命周期感知流程

Lifecycle 的设计原理

Lifecycle 整体上采用了观察者模式,主要依赖于三个类:LifecycleOwnerLifecycleRegistryLifecycleObserver

  • LifecycleOwner: 接口,其实现类表示具有生命周期,也就是被观察者。 Activity 和 Fragment 都实现了 LifecycleOwner 接口。
public interface LifecycleOwner {/*** Returns the Lifecycle of the provider.** @return The lifecycle of the provider.*/public val lifecycle: Lifecycle
}
  • LifecycleRegistry: Lifecycle 的实现类,负责管理 LifecycleOwner 的生命周期状态,并将这些状态通知给已注册的观察者。每个 LifecycleOwner 都对应一个 LifecycleRegistry
open class LifecycleRegistry private constructor(provider: LifecycleOwner,private val enforceMainThread: Boolean
) : Lifecycle() {
...private var observerMap = FastSafeIterableMap<LifecycleObserver, ObserverWithState>()private var state: State = State.INITIALIZEDprivate val lifecycleOwner: WeakReference<LifecycleOwner>init {lifecycleOwner = WeakReference(provider)}@MainThread@Deprecated("Override [currentState].")open fun markState(state: State) {enforceMainThreadIfNeeded("markState")currentState = state}
...
}
  • LifecycleObserver: 空接口,表示一个可以观察 LifecycleOwner 生命周期状态的组件,也就是观察者,真正具有使用意义的是它的子接口。
    • LifecycleEventObserver: LifecycleObserver 的子接口,用于监听 Lifecycle 的生命周期变化,可以获取到生命周期事件发生的具体变化。
    • DefaultLifecycleObserver: LifecycleObserver 的子接口,用于监听 Lifecycle 的生命周期变化,对生命周期的每一种事件都提供了独立的方法,适用于只需要知道某些生命周期事件的场景。
public interface LifecycleObserverpublic fun interface LifecycleEventObserver : LifecycleObserver {/*** Called when a state transition event happens.** @param source The source of the event* @param event The event*/public fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event)
}public interface DefaultLifecycleObserver : LifecycleObserver {/*** Notifies that `ON_CREATE` event occurred.*** This method will be called after the [LifecycleOwner]'s `onCreate`* method returns.** @param owner the component, whose state was changed*/public fun onCreate(owner: LifecycleOwner) {}/*** Notifies that `ON_START` event occurred.*** This method will be called after the [LifecycleOwner]'s `onStart` method returns.** @param owner the component, whose state was changed*/public fun onStart(owner: LifecycleOwner) {}/*** Notifies that `ON_RESUME` event occurred.*** This method will be called after the [LifecycleOwner]'s `onResume`* method returns.** @param owner the component, whose state was changed*/public fun onResume(owner: LifecycleOwner) {}/*** Notifies that `ON_PAUSE` event occurred.*** This method will be called before the [LifecycleOwner]'s `onPause` method* is called.** @param owner the component, whose state was changed*/public fun onPause(owner: LifecycleOwner) {}/*** Notifies that `ON_STOP` event occurred.*** This method will be called before the [LifecycleOwner]'s `onStop` method* is called.** @param owner the component, whose state was changed*/public fun onStop(owner: LifecycleOwner) {}/*** Notifies that `ON_DESTROY` event occurred.*** This method will be called before the [LifecycleOwner]'s `onDestroy` method* is called.** @param owner the component, whose state was changed*/public fun onDestroy(owner: LifecycleOwner) {}
}

Lifecycle 整体的设计原理如下:

  1. LifecycleOwner 在创建时会创建一个 Lifecycle 实例。
  2. Lifecycle 实例本质就是 LifecycleRegistry,负责管理 LifecycleOwner 的生命周期状态,并将这些状态通知给已注册的所有观察者。
  3. LifecycleObserver在收到状态变化通知后,可以根据状态变化执行相应的操作。

Lifecycle 的使用

Android 预定义的 LifecycleOwner 有 3 个:Activity(具体实现在 androidx.activity.ComponentActivity)、Fragment 和应用进程级别的 ProcessLifecycleOwner。前两个就不多说了,第3个 ProcessLifecycleOwner 则提供整个应用进程级别的生命周期,能够支持非毫秒级别精度监听应用前后台切换的场景。

Lifecycle 通过 addObserver(LifecycleObserver) 方法注册观察者,支持通过注解或非注解的方式注册观察者,共分为3种方式。其中注解方式已被废弃,在此就不多说了。另外两种方式分别为注册一个 LifecycleEventObserver 观察者和注册一个 DefaultLifecycleObserver 观察者。

/*** Annotation that can be used to mark methods on {@link LifecycleObserver} implementations that* should be invoked to handle lifecycle events.** @deprecated This annotation required the usage of code generation or reflection, which should* be avoided. Use {@link DefaultLifecycleObserver} or* {@link LifecycleEventObserver} instead.*/
@SuppressWarnings("unused")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Deprecated
public @interface OnLifecycleEvent {Lifecycle.Event value();
}

注册一个 LifecycleEventObserver 观察者,可以获取到生命周期事件发生的具体变化:

lifecycle.addObserver(object : LifecycleEventObserver {override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {when (event) {ON_CREATE -> {}ON_START -> {}ON_RESUME -> {}ON_PAUSE -> {}ON_STOP -> {}ON_DESTROY -> {}ON_ANY -> {}}}
})

注册一个 DefaultLifecycleObserver 观察者,可以按需重写生命周期事件监听:

lifecycle.addObserver(object : DefaultLifecycleObserver {override fun onStart(owner: LifecycleOwner) {}override fun onStop(owner: LifecycleOwner) {}override fun onDestroy(owner: LifecycleOwner) {}
})

对于向 ProcessLifecycleOwner 注册观察者,需要先通过 ProcessLifecycleOwner.get().lifecycle 的方式获取 lifecycle:

ProcessLifecycleOwner.get().lifecycle.addObserver(object: LifecycleEventObserver{override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {...}
})

自定义 LifecycleOwner

Lifecycle 的观察者必须绑定到 LifecycleOwner 上,一般来说,我们通过对 Android 预定义的 LifecycleOwner 进行 addObserver 即可,但如果需要自定义 LifecycleOwner,具体步骤就是实现 LifecycleOwner 并在内部将生命周期事件分发给 Lifecycle 实现类 LifecycleRegistry

class MyLifecycleOwner : LifecycleOwner {private val mLifecycleRegistry = LifecycleRegistry(this)override fun getLifecycle() = mLifecycleRegistryfun create() {mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)}fun start() {mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START)}fun stop() {mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP)}...
}

解析 Lifecycle

Lifecycle 注册观察者

Lifecycle#addObserver() 最终会分发到其实现类 LifecycleRegistry 中,其中会将观察者和观察者持有的状态包装为一个节点,并且在注册时将观察者状态同步推进到与宿主 LifecycleOwner 相同的状态中。

open class LifecycleRegistry private constructor(provider: LifecycleOwner,private val enforceMainThread: Boolean
) : Lifecycle() {
...//生命周期观察者集合private var observerMap = FastSafeIterableMap<LifecycleObserver, ObserverWithState>()//当前生命周期状态,默认为初始化状态private var state: State = State.INITIALIZED//持有生命周期的宿主,弱引用持有,防止内存泄漏private val lifecycleOwner: WeakReference<LifecycleOwner>init {lifecycleOwner = WeakReference(provider)}//添加观察者override fun addObserver(observer: LifecycleObserver) {//观察者的初始状态:要么是 DESTROYED,要么是 INITIALIZED,确保观察者可以接受到完整的事件流val initialState = if (state == State.DESTROYED) State.DESTROYED else State.INITIALIZED//将观察者和观察者持有的状态包装为一个节点val statefulObserver = ObserverWithState(observer, initialState)//加入到观察者集合中val previous = observerMap.putIfAbsent(observer, statefulObserver)//如果上一步添加成功了,putIfAbsent会返回nullif (previous != null) {return}//生命周期宿主已被回收,直接returnval lifecycleOwner = lifecycleOwner.get()?: // it is null we should be destroyed. Fallback quicklyreturn//当前在添加的观察者数量!=0||正在处理事件val isReentrance = addingObserverCounter != 0 || handlingEvent//将观察者推进到宿主最新的状态,先获取到最新状态var targetState = calculateTargetState(observer)addingObserverCounter++//如果当前观察者状态小于当前生命周期所在状态&&这个观察者已经被存到了观察者列表中//while一直循环,直到观察者状态同步到当前生命周期所在状态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--}//移除观察者override fun removeObserver(observer: LifecycleObserver) {observerMap.remove(observer)}//观察者及其观察状态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}}
...
}

Lifecycle 注册观察者的逻辑就是上面这些了,主要步骤如下:

  1. 初始化观察者的状态。
  2. 将观察者和观察者持有的状态包装为一个节点。
  3. 将观察者和其状态加入到 map 集合中。
  4. 获取当前 LifecycleOwner 生命周期状态。
  5. while 循环,将观察者状态同步推进到与宿主 LifecycleOwner 相同的状态。

Lifecycle 适配不同类型的观察者

上面说到了注册观察者的时候会将观察者和观察者持有的状态包装为一个节点 ObserverWithState,而在 ObserverWithState 中会将外部传入的所有 LifecycleObserver 通过 Lifecycling 包装成 LifecycleEventObserver 对象。之所以要这么做就是为了适配不同类型的观察者,Lifecycling 就是适配层。

  1. LifecycleObserver 本身是个空接口,实际使用的是它两个子接口 LifecycleEventObserverDefaultLifecycleObserver,开发者自己实现的自定义 Observer 可能同时实现了这两个接口或者实现了任一接口,LifecycleRegistry 必须在有事件触发的时候通知观察者存在的所有接口方法。
  2. 上面讲到注册观察者的方式还有注解的方式(虽然现已被废弃),但是这种方式下就需要通过反射来实现事件通知了。

Lifecycling 作为适配层,其作用就是对外部传入的 Observer 进行类型判断、接口回调、反射调用等一系列操作,将这一系列的逻辑给封装起来,对传入的 Observer 统一包装成 LifecycleEventObserver 对象,仅仅开放一个 onStateChanged 方法即可让 LifecycleRegistry 完成整个事件分发,从而使得整个流程会更加清晰明了且职责分明。

public object Lifecycling {@JvmStatic@Suppress("DEPRECATION")public fun lifecycleEventObserver(`object`: Any): LifecycleEventObserver {val isLifecycleEventObserver = `object` is LifecycleEventObserverval isDefaultLifecycleObserver = `object` is DefaultLifecycleObserver// 1. 观察者同时实现 LifecycleEventObserver 和 DefaultLifecycleObserverif (isLifecycleEventObserver && isDefaultLifecycleObserver) {return DefaultLifecycleObserverAdapter(`object` as DefaultLifecycleObserver,`object` as LifecycleEventObserver)}// 2. 观察者只实现 DefaultLifecycleObserverif (isDefaultLifecycleObserver) {return DefaultLifecycleObserverAdapter(`object` as DefaultLifecycleObserver, null)}// 3. 观察者只实现 LifecycleEventObserverif (isLifecycleEventObserver) {return `object` as LifecycleEventObserver}// 4. 观察者使用注解方式val klass: Class<*> = `object`.javaClassval type = getObserverConstructorType(klass)if (type == GENERATED_CALLBACK) {val constructors = classToAdapters[klass]!!if (constructors.size == 1) {val generatedAdapter = createGeneratedAdapter(constructors[0], `object`)return SingleGeneratedAdapterObserver(generatedAdapter)}val adapters: Array<GeneratedAdapter> = Array(constructors.size) { i ->createGeneratedAdapter(constructors[i], `object`)}return CompositeGeneratedAdaptersObserver(adapters)}// 反射调用return ReflectiveGenericLifecycleObserver(`object`)}
}

DefaultLifecycleObserverAdapter 实现了 LifecycleEventObserver 接口,用于在收到 Lifecycle 生命周期事件状态变化时,对两个构造参数 DefaultLifecycleObserverLifecycleEventObserver 进行事件转发。

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)}
}

Lifecycle 分发生命周期事件

在注册观察者的时候,将观察者状态同步推进到与宿主 LifecycleOwner 相同的状态,用的是 while 循环,每一次获取当前状态接下来的事件并进行事件分发,一次一步,直到状态同步。

public enum class Event {public companion object {/*** Returns the [Lifecycle.Event] that will be reported by a [Lifecycle]* leaving the specified [Lifecycle.State] to a higher state, or `null`* if there is no valid event that can move up from the given state.** @param state the lower state that the returned event will transition up from* @return the event moving up the lifecycle phases from state*/@JvmStaticpublic fun upFrom(state: State): Event? {return when (state) {State.INITIALIZED -> ON_CREATEState.CREATED -> ON_STARTState.STARTED -> ON_RESUMEelse -> null}}}
}

结合 Lifecycle 分发生命周期状态的流程图:
Lifecycle生命周期感知流程

如果在 Activity onResume 之后向其添加了一个 LifecycleEventObserver,此时观察者初始状态是 INITIALIZED,需要同步到与宿主 LifecycleOwner 相同的状态,也就是RESUMED,观察者会依次收到 ON_CREATE、ON_START、ON_RESUME 三个Event事件。

当宿主 LifecycleOwner 生命周期发生变化时,会将生命周期事件分发到 LifecycleRegistry#handleLifecycleEvent(Lifecycle.Event),将观察者的状态回调到最新的状态上。

    //分发生命周期事件open fun handleLifecycleEvent(event: Event) {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()}"}state = nextif (handlingEvent || addingObserverCounter != 0) {newEventOccurred = true// we will figure out what to do on upper level.return}handlingEvent = true//状态同步sync()handlingEvent = falseif (state == State.DESTROYED) {observerMap = FastSafeIterableMap()}}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.")while (!isSynced) {newEventOccurred = falseif (state < observerMap.eldest()!!.value.state) {//状态回退backwardPass(lifecycleOwner)}val newest = observerMap.newest()if (!newEventOccurred && newest != null && state > newest.value.state) {//状态前进forwardPass(lifecycleOwner)}}newEventOccurred = false}private fun forwardPass(lifecycleOwner: LifecycleOwner) {@Suppress()val ascendingIterator: Iterator<Map.Entry<LifecycleObserver, ObserverWithState>> =observerMap.iteratorWithAdditions()while (ascendingIterator.hasNext() && !newEventOccurred) {val (key, observer) = ascendingIterator.next()while (observer.state < state && !newEventOccurred && observerMap.contains(key)) {pushParentState(observer.state)val event = Event.upFrom(observer.state)?: throw IllegalStateException("no event up from ${observer.state}")observer.dispatchEvent(lifecycleOwner, event)popParentState()}}}

首先更新状态 state,然后通过 sync() 方法将状态同步到所有观察者,sync() 方法在添加观察者时也被调用过。在 sync() 方法中,状态需要回退则调用 backwardPass 方法,状态需要前进则调用 forwardPass 方法。两个方法逻辑相似,这边就只贴出了 forwardPass 方法,来看一下如何处理状态前进的。可以发现里面使用了两层 while 循环,外层 while 循环遍历所有观察者,内层 while 循环与注册观察者时状态同步的 while 循环内容一致,每一次获取当前状态接下来的事件并进行事件分发,一次一步,直到状态同步。

最终 observer.dispatchEvent 是通过 ObserverWithState#dispatchEvent() 分发事件,我们已经知道 ObserverWithState 里使用了适配器模式对 Observer 统一包装成 LifecycleEventObserver 对象,仅仅开放一个 onStateChanged 方法,ObserverWithState#dispatchEvent() 里就是通过 lifecycleObserver.onStateChanged 通知到观察者,后续就是上一点提到的 Lifecycling 适配层的逻辑了。

Lifecycle 感知 Activity 生命周期

知道了怎么注册的观察者以及如何将生命周期事件分发到观察者,最后来看一下 Lifecycle 是如何感知到宿主 LifecycleOwner 的生命周期进而继续后续的操作的。

上面讲到当宿主 LifecycleOwner 生命周期发生变化时,会将生命周期事件分发到 LifecycleRegistry#handleLifecycleEvent(Lifecycle.Event),这不就简单了,在宿主 LifecycleOwner 生命周期的相关方法直接调用不就好了。

handleLifecycleEvent调用处

通过查看 LifecycleRegistry#handleLifecycleEvent 的调用,可以看到在 DialogFragmentFragmenActivity 里就是通过在生命周期的相关方法里直接调用 LifecycleRegistry#handleLifecycleEvent(Lifecycle.Event)将生命周期事件分发的,但是并没有出现我们常用的 ComponentActivity,这是因为上述这种方法会造成对基类的入侵,使得基类越发膨胀,所以在 ComponentActivity 中使用了 ReportFragment 承载 Lifecycle 在 activity 的具体逻辑。

感知宿主生命周期使用 ReportFragment,管理生命周期状态并将状态通知观察者使用 LifecycleRegistry,适配观察者使用 Lifecycling,这一整套流程行云流水清晰明了且职责分明。

public class ComponentActivity extends androidx.core.app.ComponentActivity implements LifecycleOwner ...{private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);@NonNull@Overridepublic Lifecycle getLifecycle() {return mLifecycleRegistry;}@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {...super.onCreate(savedInstanceState);ReportFragment.injectIfNeededIn(this);...}
}

通过 ReportFragment#injectIfNeededIn(Activity) 接收 Activity。

open class ReportFragment() : android.app.Fragment() {companion object {@JvmStaticfun injectIfNeededIn(activity: Activity) {if (Build.VERSION.SDK_INT >= 29) {// On API 29+, we can register for the correct Lifecycle callbacks directlyLifecycleCallbacks.registerIn(activity)}// Prior to API 29 and to maintain compatibility with older versions of// ProcessLifecycleOwner (which may not be updated when lifecycle-runtime is updated and// need to support activities that don't extend from FragmentActivity from support lib),// use a framework fragment to get the correct timing of Lifecycle eventsval 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()}}}
}
  • 第一种情况:在sdk29以下,通过向 Activity 添加一个空白界面的 Fragment,间接获得 Activity 的各个生命周期事件的回调通知。
  • 第二种情况:在sdk29及以上,通过向 Activity 注册生命周期回调的方式来监听。这里应该还牵扯到对旧版本 ProcessLifecycleOwner 和 support 库的兼容,所以此时也会同时执行第一种情况的操作。

之所以这么区分是因为 registerActivityLifecycleCallbacks 中的 onActivityPostXXXonActivityPreXXX 等方法是sdk29时新添加的方法。

    @RequiresApi(29)internal class LifecycleCallbacks : Application.ActivityLifecycleCallbacks {override fun onActivityCreated(activity: Activity,bundle: Bundle?) {}override fun onActivityPostCreated(activity: Activity,savedInstanceState: Bundle?) {dispatch(activity, Lifecycle.Event.ON_CREATE)}override fun onActivityStarted(activity: Activity) {}override fun onActivityPostStarted(activity: Activity) {dispatch(activity, Lifecycle.Event.ON_START)}override fun onActivityResumed(activity: Activity) {}override fun onActivityPostResumed(activity: Activity) {dispatch(activity, Lifecycle.Event.ON_RESUME)}override fun onActivityPrePaused(activity: Activity) {dispatch(activity, Lifecycle.Event.ON_PAUSE)}override fun onActivityPaused(activity: Activity) {}override fun onActivityPreStopped(activity: Activity) {dispatch(activity, Lifecycle.Event.ON_STOP)}override fun onActivityStopped(activity: Activity) {}override fun onActivitySaveInstanceState(activity: Activity,bundle: Bundle) {}override fun onActivityPreDestroyed(activity: Activity) {dispatch(activity, Lifecycle.Event.ON_DESTROY)}override fun onActivityDestroyed(activity: Activity) {}companion object {@JvmStaticfun registerIn(activity: Activity) {activity.registerActivityLifecycleCallbacks(LifecycleCallbacks())}}}

一些小细节,在sdk29及以上,通过向 Activity 注册生命周期回调的方式来监听时,会在 Activity 的 onCreate、onStart、onResume 等方法被调用后发送相应的 Event 事件,并在 onPause、onStop、onDestroy 等方法被调用前发送相应的 Event 事件。

Lifecycle 的运用实践案例

Lifecycle 作为 JetPack 的基石,在 JetPack 里已有了许多的运用实践:

  1. LifecycleOwner.lifecycleScope,具有生命周期感知的协程作用域,当宿主 destroy 时,会自动取消协程。
  2. LiveData,具有生命周期感知能力,当宿主状态活跃时(状态至少为 STARTED),才会发送数据,同时当宿主 destroy 时,会自动移除观察者。
  3. Flow#flowWithLifecycle(),当宿主状态活跃时(默认状态至少为 STARTED),启动一个新协程用于接收 flow 数据,当宿主状态不活跃时,取消该协程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/418890.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAM 2:分割图像和视频中的任何内容

文章目录 摘要1 引言2 相关工作3 任务&#xff1a;可提示视觉分割4 模型5 数据5.1 数据引擎5.2 SA-V数据集 6 零样本实验6.1 视频任务6.1.1 提示视频分割6.1.2 半监督视频对象分割6.1.3 公平性评估 6.2 图像任务 7 与半监督VOS的最新技术的比较8 数据和模型消融8.1 数据消融8.2…

RT-Thread(Nano版本)的快速移植(基于NUCLEO-F446RE)

目录 概述 1 RT-Thread 1.1 RT-Thread的版本 1.2 认识Nano版本 2 STM32F446U上移植RT-Thread 2.1 STM32Cube创建工程 2.2 移植RT-Thread 2.2.1 安装RT-Thread Packet 2.2.2 加载RT-Thread 2.2.3 匹配相关接口 2.2.3.1 初次编译代码 2.2.3.2 匹配端口 2.2.4 移植FinSH…

时间同步服务

多主机协作工作时&#xff0c;各个主机的时间同步很重要&#xff0c;时间不一致会造成很多重要应用的故障&#xff0c;如&#xff1a;加密协 议&#xff0c;日志&#xff0c;集群等。 利用NTP&#xff08;Network Time Protocol&#xff09; 协议使网络中的各个计算机时间达到…

OceanBase 4.x 存储引擎解析:如何让历史库场景成本降低50%+

据国际数据公司&#xff08;IDC&#xff09;的报告显示&#xff0c;预计到2025年&#xff0c;全球范围内每天将产生高达180ZB的庞大数据量&#xff0c;这一趋势预示着企业将面临着更加严峻的海量数据处理挑战。随着数据日渐庞大&#xff0c;一些存储系统会出现诸如存储空间扩展…

AF透明模式/虚拟网线模式组网部署

透明模式组网 实验拓扑 防火墙基本配置 接口配置 eth1 eth3 放通策略 1. 内网用户上班时间&#xff08;9:00-17:00&#xff09;不允许看视频、玩游戏及网上购物&#xff0c;其余时 间访问互联网不受限制&#xff1b;&#xff08;20 分&#xff09; 应用控制策略 2. 互联…

IBM Storwize V7000存储控制器故障节点报错574

背景&#xff1a;由于客户机房搬迁&#xff0c;需要下电迁移设备。该存储自2016年投入生产使用后&#xff0c;从未关过机&#xff0c;已正常运行七八年时间&#xff0c;期间只更换过硬盘&#xff0c;无其他硬件故障。 在GUI界面点击关闭系统后&#xff0c;大概等了40分钟&…

说一下解除docker限制内存警告

有时候docker要对容器使用的内存做出限制&#xff0c;通常的做法是使用参数 -m 例如&#xff1a; docker run -m 512M表示容器内存最大不能超过512M。 但这样做&#xff0c;在ubuntu会看到以下警告 WARNING: Your kernel does not support swap limit capabilitiesdocker官方…

从监控到智能:EasyCVR视频汇聚平台助力加油站安全监管升级转型

随着科技的不断进步&#xff0c;视频监控技术在各个行业的应用日益广泛&#xff0c;尤其在加油站这一关键领域&#xff0c;视频智能监管系统的应用显得尤为重要。TSINGSEE青犀视频EasyCVR视频汇聚平台作为一款基于“云-边-端”一体化架构的视频融合与AI智能分析平台&#xff0c…

JAVA读写Excel(jxl,poi,easyExcel)

目录 一、需求描述 二、具体操作Excel的常用方法 方法一&#xff1a; 使用jxl 方法二&#xff1a; POI 方法三&#xff1a;EasyExcel 三、总结 一、需求描述 前端有时候会传送 Excel 文件给后端&#xff08;Java&#xff09;去解析&#xff0c;那我们作为后端该如何实现…

Jenkins+Svn+Vue自动化构建部署前端项目(保姆级图文教程)

目录 介绍 准备工作 配置jenkins 构建部署任务 常见问题 介绍 在平常开发前端vue项目时,我们通常需要将vue项目进行打包构建,将打包好的dist目录下的静态文件上传到服务器上,但是这种繁琐的操作是比较浪费时间的,可以使用jenkins进行自动化构建部署前端vue 准备工作 准备…

AI模型的未来之路:全能与专精的博弈与共生

人工智能(AI)领域正迅速发展,伴随着技术的不断进步,AI模型的应用范围也在不断扩展。当前,AI模型的设计和使用面临两个主要趋势:全能型模型和专精型模型。这两者之间的博弈与共生将塑造未来的AI技术格局。本文将从以下七个方面探讨AI模型的未来之路,并提供实用的代码示例…

ROS1 + Realsense d455 固件安装+读取rostopic数据

目录 安装固件&#xff08;一定要匹配&#xff09;ROS1 wrapper 安装方法Realsense SDK 安装方法Realsense Firmware 安装方法 修改roslaunch配置文件&#xff0c;打开双目图像和IMU数据其他坑点参考链接 安装固件&#xff08;一定要匹配&#xff09; 如果你是使用ROS1获取rea…

Python数据分析-绘制图表

示例1&#xff1a; from pyecharts.charts import Bar # 柱状图 from pyecharts import options as optsfrom pyecharts.render import make_snapshotbar Bar() bar.add_xaxis([一月, 二月, 三月, 四月, 五月]) bar.add_yaxis("销售额", [10, 20, 15, 25, 30])# 配…

安卓framework单屏幕Display秒双/多屏互动相关需求改进-wms实战开发

背景 前面已经给学员朋友们分享过单屏秒变双屏的成果展示&#xff0c;具体详情可以点击这里&#xff1a; https://mp.weixin.qq.com/s/KdYTLMuXiBdjM0kZmYKzPg 一些vip学员朋友也纷纷求助马哥的实现patch代码&#xff0c;想用于公司的实战项目实现。但是在公司需求实现要求和…

Python(TensorFlow)和MATLAB及Java光学像差导图

&#x1f3af;要点 几何光线和波前像差计算入瞳和出瞳及近轴光学计算波前像差特征矩阵方法计算光谱反射率、透射率和吸光度透镜像差和绘制三阶光线像差图和横向剪切干涉图分析瞳孔平面焦平面和大气湍流建模神经网络光学像差计算透镜光线传播几何偏差计算像差和像散色差纠正对齐…

八、Maven总结

1.为什么要学习Maven&#xff1f; 2.Maven 也可以配华为云和腾讯云等。 3.IDEA整合Maven 4.IDEA基于Maven进行工程的构建 5.基于Maven进行依赖管理&#xff08;重点&#xff09; 6. Maven的依赖传递和依赖冲突 7. Maven工程继承和聚合 8.仓库及查找顺序

应用层协议Http

Http协议 1.1 什么是http协议 在进行网络通信时&#xff0c;应用层协议一般都是程序员自己写的&#xff0c;但是有一些大佬其实已经定义出了一些现成的应用层协议&#xff0c;例如&#xff1a;HTTP&#xff08;超文本传输协议&#xff09;、FTP&#xff08;文件传输协议&#…

SAP学习笔记 - 开发04 - Fiori UI5 开发环境搭建

上一章学习了 CDSView开发环境的搭建&#xff0c;以及CDSView相关的知识。 SAP学习笔记 - 开发03 - CDSView开发环境搭建&#xff0c;Eclipse中连接SAP&#xff0c;CDSView创建-CSDN博客 本章继续学习SAP开发相关的内容&#xff0c; - Fiori UI5的开发环境搭建 - 安装VSCode …

百度飞将 paddle ,实现贝叶斯神经网络 bayesue neure network bnn,aistudio公开项目 复现效果不好

论文复现赛&#xff1a;贝叶斯神经网络 - 飞桨AI Studio星河社区 https://github.com/hrdwsong/BayesianCNN-Paddle 论文复现&#xff1a;Weight Uncertainty in Neural Networks 本项目复现时遇到一个比较大的问题&#xff0c;用pytorch顺利跑通源代码后&#xff0c;修改至pad…

【Python报错已解决】 AttributeError: ‘move_to‘ requires a WebElement

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;检查元素选择器2.2 方法…