Known direct subclasses
LifecycleRegistry

A Lifecycle implementation that manages multiple LifecycleObservers.


Defines an object with a lifecycle state control flow.

Commonly implemented by UI container classes (such as Activities and Fragments on Android) or custom components to expose their lifecycle to other components.

Event.ON_CREATE, Event.ON_START, Event.ON_RESUME events are dispatched after the LifecycleOwner's related method returns. Event.ON_PAUSE, Event.ON_STOP, Event.ON_DESTROY events are dispatched before the LifecycleOwner's related method is called. This gives you certain guarantees on which state the owner is in.

To observe lifecycle events, call addObserver passing an object that implements either DefaultLifecycleObserver or LifecycleEventObserver.

See also
Lifecycle.State

for the valid lifecycle states.

Lifecycle.Event

for the transition events between states.

Summary

Nested types

Represents a transition event triggered by a change in the LifecycleOwner's state.

Represents the current lifecycle state of a LifecycleOwner.

Public constructors

Cmn

Public functions

abstract Unit

Adds a LifecycleObserver to receive LifecycleOwner state changes.

Cmn
abstract Unit

Removes the given observer from the list of registered observers.

Cmn

Public properties

abstract Lifecycle.State

The current State of the Lifecycle.

Cmn
open StateFlow<Lifecycle.State>

Returns a StateFlow where the StateFlow.value represents the current State of this Lifecycle.

Cmn

Extension functions

State<Lifecycle.State>

Collects values from the Lifecycle.currentStateFlow and represents its latest value via State.

Cmn
inline LifecycleObserver
Lifecycle.addObserver(
    crossinline action: LifecycleObserver.(source: LifecycleOwner, event: Lifecycle.Event) -> Unit
)

Adds a LifecycleObserver to this Lifecycle using the provided action.

Cmn
suspend T
<T : Any?> Lifecycle.whenCreated(block: suspend CoroutineScope.() -> T)

This function is deprecated. whenCreated has been deprecated because it runs the block on a pausing dispatcher that suspends, rather than cancels work when the lifecycle state goes below the given state.

android
suspend T
<T : Any?> Lifecycle.whenResumed(block: suspend CoroutineScope.() -> T)

This function is deprecated. whenResumed has been deprecated because it runs the block on a pausing dispatcher that suspends, rather than cancels work when the lifecycle state goes below the given state.

android
suspend T
<T : Any?> Lifecycle.whenStarted(block: suspend CoroutineScope.() -> T)

This function is deprecated. whenStarted has been deprecated because it runs the block on a pausing dispatcher that suspends, rather than cancels work when the lifecycle state goes below the given state.

android
suspend T
<T : Any?> Lifecycle.whenStateAtLeast(
    minState: Lifecycle.State,
    block: suspend CoroutineScope.() -> T
)

This function is deprecated. whenStateAtLeast has been deprecated because it runs the block on a pausing dispatcher that suspends, rather than cancels work when the lifecycle state goes below the given state.

android
suspend Unit
Lifecycle.repeatOnLifecycle(
    state: Lifecycle.State,
    block: suspend CoroutineScope.() -> Unit
)

Runs the given block in a new coroutine when this Lifecycle is at least at state and suspends the execution until this Lifecycle is Lifecycle.State.DESTROYED.

Cmn
suspend inline R
<R : Any?> Lifecycle.withCreated(crossinline block: () -> R)

Run block with this Lifecycle in a Lifecycle.State of at least Lifecycle.State.CREATED and resume with the result.

Cmn
suspend inline R
<R : Any?> Lifecycle.withResumed(crossinline block: () -> R)

Run block with this Lifecycle in a Lifecycle.State of at least Lifecycle.State.RESUMED and resume with the result.

Cmn
suspend inline R
<R : Any?> Lifecycle.withStarted(crossinline block: () -> R)

Run block with this Lifecycle in a Lifecycle.State of at least Lifecycle.State.STARTED and resume with the result.

Cmn
suspend inline R
<R : Any?> Lifecycle.withStateAtLeast(
    state: Lifecycle.State,
    crossinline block: () -> R
)

Run block with this Lifecycle in a Lifecycle.State of at least state and resume with the result.

Cmn

Extension properties

LifecycleCoroutineScope

CoroutineScope tied to this Lifecycle.

Cmn
Flow<Lifecycle.Event>

Creates a Flow of Lifecycle.Events dispatched by this Lifecycle.

Cmn

Public constructors

Lifecycle

Lifecycle()

Public functions

addObserver

@MainThread
abstract fun addObserver(observer: LifecycleObserver): Unit

Adds a LifecycleObserver to receive LifecycleOwner state changes.

Brings the given observer up to the current State of the LifecycleOwner. For example, if the LifecycleOwner is in State.STARTED, the observer receives Event.ON_CREATE and Event.ON_STARTs.

Parameters
observer: LifecycleObserver

The observer to notify.

removeObserver

@MainThread
abstract fun removeObserver(observer: LifecycleObserver): Unit

Removes the given observer from the list of registered observers.

If called while a state change is being dispatched:

  • If the given observer has not yet received that event, it will not receive it.

  • If the given observer has more than one method that observes the currently dispatched event, and at least one of them received the event, all of them receive it, and removal occurs afterward.

Parameters
observer: LifecycleObserver

The observer to remove.

Public properties

currentState

abstract val currentStateLifecycle.State

The current State of the Lifecycle.

currentStateFlow

open val currentStateFlowStateFlow<Lifecycle.State>

Returns a StateFlow where the StateFlow.value represents the current State of this Lifecycle.

Extension functions

Lifecycle.currentStateAsState

@Composable
fun Lifecycle.currentStateAsState(): State<Lifecycle.State>

Collects values from the Lifecycle.currentStateFlow and represents its latest value via State. The StateFlow.value is used as an initial value. Every time there would be new value posted into the StateFlow the returned State will be updated causing recomposition of every State.value usage.

Lifecycle.addObserver

inline fun Lifecycle.addObserver(
    crossinline action: LifecycleObserver.(source: LifecycleOwner, event: Lifecycle.Event) -> Unit
): LifecycleObserver

Adds a LifecycleObserver to this Lifecycle using the provided action.

Invokes action whenever a Lifecycle.Event occurs.

Parameters
crossinline action: LifecycleObserver.(source: LifecycleOwner, event: Lifecycle.Event) -> Unit

The action invoked on each Lifecycle.Event, providing the LifecycleOwner and the specific Lifecycle.Event.

Returns
LifecycleObserver

the added LifecycleObserver instance (can be used to later remove it).

Lifecycle.whenCreated

suspend fun <T : Any?> Lifecycle.whenCreated(block: suspend CoroutineScope.() -> T): T

Runs the given block when the Lifecycle is at least in Lifecycle.State.CREATED state.

See also
whenStateAtLeast

for details

Lifecycle.whenResumed

suspend fun <T : Any?> Lifecycle.whenResumed(block: suspend CoroutineScope.() -> T): T

Runs the given block when the Lifecycle is at least in Lifecycle.State.RESUMED state.

See also
whenStateAtLeast

for details

Lifecycle.whenStarted

suspend fun <T : Any?> Lifecycle.whenStarted(block: suspend CoroutineScope.() -> T): T

Runs the given block when the Lifecycle is at least in Lifecycle.State.STARTED state.

See also
whenStateAtLeast

for details

Lifecycle.whenStateAtLeast

suspend fun <T : Any?> Lifecycle.whenStateAtLeast(
    minState: Lifecycle.State,
    block: suspend CoroutineScope.() -> T
): T

Runs the given block on a CoroutineDispatcher that executes the block on the main thread and suspends the execution unless the Lifecycle's state is at least minState.

If the Lifecycle moves to a lesser state while the block is running, the block will be suspended until the Lifecycle reaches to a state greater or equal to minState.

Note that this won't effect any sub coroutine if they use a different CoroutineDispatcher. However, the block will not resume execution when the sub coroutine finishes unless the Lifecycle is at least in minState.

If the Lifecycle is destroyed while the block is suspended, the block will be cancelled which will also cancel any child coroutine launched inside the block.

If you have a try finally block in your code, the finally might run after the Lifecycle moves outside the desired state. It is recommended to check the Lifecycle.currentState before accessing the UI. Similarly, if you have a catch statement that might catch CancellationException, you should check the Lifecycle.currentState before accessing the UI. See the sample below for more details.

// running a block of code only if lifecycle is STARTED
viewLifecycle.whenStateAtLeast(Lifecycle.State.STARTED) {
// here, we are on the main thread and view lifecycle is guaranteed to be STARTED or RESUMED.
// We can safely access our views.
loadingBar.visibility = View.VISIBLE
try {
// we can call any suspend function
val data = withContext(Dispatchers.IO) {
// this will run in IO thread pool. It will keep running as long as Lifecycle
// is not DESTROYED. If it is destroyed, this coroutine will be cancelled as well.
// However, we CANNOT access Views here.

// We are using withContext(Dispatchers.IO) here just for demonstration purposes.
// Such code should live in your business logic classes and your UI should use a
// ViewModel (or similar) to access it.
api.getUser()
}
// this line will execute on the main thread and only if the lifecycle is in at least
// STARTED state (STARTED is the parameter we've passed to whenStateAtLeast)
// Because of this guarantee, we can safely access the UI again.
loadingBar.visibility = View.GONE
nameTextView.text = user.name
lastNameTextView.text = user.lastName
} catch(ex : UserNotFoundException) {
// same as above, this code can safely access UI elements because it only runs if
// view lifecycle is at least STARTED
loadingBar.visibility = View.GONE
showErrorDialog(ex)
} catch(th : Throwable) {
// Unlike the catch statement above, this catch statements it too generic and might
// also catch the CancellationException. Before accessing UI, you should check isActive
// or lifecycle state
if (viewLifecycle.currentState >= Lifecycle.State.STARTED) {
// here you can access the view because you've checked the coroutine is active
}
} finally {
// in case of cancellation, this line might run even if the Lifecycle is not DESTROYED.
// You cannot access Views here unless you check `isActive` or lifecycle state
if (viewLifecycle.currentState >= Lifecycle.State.STARTED) {
// safe to access views
} else {
// not safe to access views
}
}
}
Parameters
minState: Lifecycle.State

The desired minimum state to run the block.

block: suspend CoroutineScope.() -> T

The block to run when the lifecycle is at least in minState.

Returns
T The return value of the [block]

Lifecycle.repeatOnLifecycle

suspend fun Lifecycle.repeatOnLifecycle(
    state: Lifecycle.State,
    block: suspend CoroutineScope.() -> Unit
): Unit

Runs the given block in a new coroutine when this Lifecycle is at least at state and suspends the execution until this Lifecycle is Lifecycle.State.DESTROYED.

The block will cancel and re-launch as the lifecycle moves in and out of the target state.

class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
/* ... */
// Runs the block of code in a coroutine when the lifecycle is at least STARTED.
// The coroutine will be cancelled when the ON_STOP event happens and will
// restart executing if the lifecycle receives the ON_START event again.
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
uiStateFlow.collect { uiState ->
updateUi(uiState)
}
}
}
}
}

The best practice is to call this function when the lifecycle is initialized. For example, onCreate in an Activity, or onViewCreated in a Fragment. Otherwise, multiple repeating coroutines doing the same could be created and be executed at the same time.

Repeated invocations of block will run serially, that is they will always wait for the previous invocation to fully finish before re-starting execution as the state moves in and out of the required state.

Thread Safety: This function always executes the lifecycle registration and synchronization on Dispatchers.Main.immediate. If the caller coroutine context runs on a different dispatcher, it yields to the main dispatcher. The target block also executes on the main dispatcher.

Warning: Lifecycle.State.INITIALIZED is not allowed in this API. Passing it as a parameter will throw an IllegalArgumentException.

Parameters
state: Lifecycle.State

Lifecycle.State in which block runs in a new coroutine. That coroutine will cancel if the lifecycle falls below that state, and will restart if it's in that state again.

block: suspend CoroutineScope.() -> Unit

The block to run when the lifecycle is at least in state state.

Lifecycle.withCreated

suspend inline fun <R : Any?> Lifecycle.withCreated(crossinline block: () -> R): R

Run block with this Lifecycle in a Lifecycle.State of at least Lifecycle.State.CREATED and resume with the result. Throws the CancellationException if the lifecycle has reached Lifecycle.State.DESTROYED by the time of the call or before block is able to run.

Lifecycle.withResumed

suspend inline fun <R : Any?> Lifecycle.withResumed(crossinline block: () -> R): R

Run block with this Lifecycle in a Lifecycle.State of at least Lifecycle.State.RESUMED and resume with the result. Throws the CancellationException if the lifecycle has reached Lifecycle.State.DESTROYED by the time of the call or before block is able to run.

Lifecycle.withStarted

suspend inline fun <R : Any?> Lifecycle.withStarted(crossinline block: () -> R): R

Run block with this Lifecycle in a Lifecycle.State of at least Lifecycle.State.STARTED and resume with the result. Throws the CancellationException if the lifecycle has reached Lifecycle.State.DESTROYED by the time of the call or before block is able to run.

Lifecycle.withStateAtLeast

suspend inline fun <R : Any?> Lifecycle.withStateAtLeast(
    state: Lifecycle.State,
    crossinline block: () -> R
): R

Run block with this Lifecycle in a Lifecycle.State of at least state and resume with the result. Throws the CancellationException if the lifecycle has reached Lifecycle.State.DESTROYED by the time of the call or before block is able to run.

Extension properties

Lifecycle.coroutineScope

val Lifecycle.coroutineScopeLifecycleCoroutineScope

CoroutineScope tied to this Lifecycle.

Canceled when the Lifecycle is destroyed. Bound to Dispatchers.Main.immediate.

Lifecycle.eventFlow

val Lifecycle.eventFlowFlow<Lifecycle.Event>

Creates a Flow of Lifecycle.Events dispatched by this Lifecycle.