abstract class Lifecycle

Known direct subclasses
LifecycleRegistry

An implementation of Lifecycle that can handle multiple observers.


Defines an object that has an Android Lifecycle. Fragment and FragmentActivity classes implement LifecycleOwner interface which has the LifecycleOwner.getLifecycle method to access the Lifecycle. You can also implement LifecycleOwner in your own classes.

Event.ON_CREATE, Event.ON_START, Event.ON_RESUME events in this class are dispatched after the LifecycleOwner's related method returns. Event.ON_PAUSE, Event.ON_STOP, Event.ON_DESTROY events in this class are dispatched before the LifecycleOwner's related method is called. For instance, Event.ON_START will be dispatched after onStart returns, Event.ON_STOP will be dispatched before onStop 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.

Summary

Nested types

Lifecycle states.

Public constructors

Public functions

abstract Unit

Adds a LifecycleObserver that will be notified when the LifecycleOwner changes state.

abstract Unit

Removes the given observer from the observers list.

Public properties

abstract Lifecycle.State

Returns the current state of the Lifecycle.

open StateFlow<Lifecycle.State>

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

Extension functions

State<Lifecycle.State>

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

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.

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.

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.

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.

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.

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.

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.

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.

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.

Extension properties

LifecycleCoroutineScope

CoroutineScope tied to this Lifecycle.

Flow<Lifecycle.Event>

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

Public constructors

Lifecycle

Added in 2.0.0
Lifecycle()

Public functions

addObserver

Added in 2.0.0
@MainThread
abstract fun addObserver(observer: LifecycleObserver): Unit

Adds a LifecycleObserver that will be notified when the LifecycleOwner changes state.

The given observer will be brought to the current state of the LifecycleOwner. For example, if the LifecycleOwner is in State.STARTED state, the given observer will receive Event.ON_CREATE, Event.ON_START events.

Parameters
observer: LifecycleObserver

The observer to notify.

removeObserver

Added in 2.0.0
@MainThread
abstract fun removeObserver(observer: LifecycleObserver): Unit

Removes the given observer from the observers list.

If this method is 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 1 method that observes the currently dispatched event and at least one of them received the event, all of them will receive the event and the removal will happen afterwards.

Parameters
observer: LifecycleObserver

The observer to be removed.

Public properties

currentState

Added in 2.0.0
abstract val currentStateLifecycle.State

Returns the current state of the Lifecycle.

Returns
Lifecycle.State

The current state of the Lifecycle.

currentStateFlow

Added in 2.7.0
open val currentStateFlowStateFlow<Lifecycle.State>

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

Returns
StateFlow<Lifecycle.State>

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

Extension functions

@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.

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

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

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

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.getCurrentState before accessing the UI. Similarly, if you have a catch statement that might catch CancellationException, you should check the Lifecycle.getCurrentState 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]
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.

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.

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.

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.

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.

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

coroutineScope

val Lifecycle.coroutineScopeLifecycleCoroutineScope

CoroutineScope tied to this Lifecycle.

This scope will be cancelled when the Lifecycle is destroyed.

This scope is bound to Dispatchers.Main.immediate

val Lifecycle.eventFlowFlow<Lifecycle.Event>

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