lifecycleScope: What It Is, Lifecycle Binding, and How It Works in Android

Author: IT Sectr Published: 2026-06-23 Reading time: 9 min

lifecycleScope — is a built-in CoroutineScope from the androidx.lifecycle library, tied to the lifecycle of an Activity, Fragment, or any LifecycleOwner, and automatically cancels coroutines when the component is destroyed. According to Google Android Developers, 2025, lifecycleScope allows you to safely launch coroutines related to the UI layer without the risk of executing code after the Activity or Fragment is destroyed. The scope is automatically cancelled when the LifecycleOwner transitions to the DESTROYED state.

Key Takeaways

  • lifecycleScope — CoroutineScope from lifecycle-runtime-ktx, cancelled on DESTROYED Lifecycle state
  • lifecycleScope.launch — launch a coroutine that is automatically cancelled when the LifecycleOwner is destroyed
  • launchWhenStarted / launchWhenResumed — deprecated methods, replaced by repeatOnLifecycle
  • repeatOnLifecycle — modern API for launching coroutines that follow a specific Lifecycle state
  • Dispatchers.Main.immediate — default dispatcher for lifecycleScope

What Is lifecycleScope in Android?

lifecycleScope is an extension property on the LifecycleOwner interface (Activity, Fragment, Service) that provides a ready-made CoroutineScope tied to the full lifecycle of the component. When the LifecycleOwner reaches the DESTROYED state, lifecycleScope automatically cancels all active coroutines.

kotlin
// In Fragment or Activity
lifecycleScope.launch {
    delay(1000)
    showSnackbar("Hello!")
}

Unlike viewModelScope, lifecycleScope is cancelled every time the LifecycleOwner is destroyed — including screen rotation. This makes it ideal for operations that should only live while a specific screen is visible.

Where lifecycleScope Is Available

lifecycleScope is available everywhere there is a LifecycleOwner:

  • Activity — AppCompatActivity inherits LifecycleOwner
  • Fragment — Fragment inherits LifecycleOwner
  • LifecycleService — a service with a lifecycle
  • ProcessLifecycleOwner — the lifecycle of the entire application
  • Custom LifecycleOwner — any object implementing LifecycleOwner

How lifecycleScope Works: Lifecycle and Automatic Cancellation

The automatic cancellation mechanism of lifecycleScope is based on subscribing to Lifecycle events. When the Lifecycle drops below CREATED to DESTROYED, the scope is cancelled.

Lifecycle States

StateDescriptionScope Active
CREATEDLifecycleOwner created, onCreate executedYes
STARTEDLifecycleOwner visible (onStart)Yes
RESUMEDLifecycleOwner in the foreground (onResume)Yes
DESTROYEDLifecycleOwner destroyed (onDestroy)No (scope cancelled)

Internal Structure of lifecycleScope

lifecycleScope is created as CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) and stored inside the Lifecycle. When the Lifecycle transitions to the DESTROYED state, scope.cancel() is called. The mechanism is implemented via LifecycleEventObserver, which subscribes to lifecycle events on the first access to the scope.

Behavior on Rotation

When the screen is rotated, the Activity is destroyed (onDestroy) and recreated. lifecycleScope is cancelled together with the old Activity, and a new scope instance is created for the new Activity. This is a fundamental difference from viewModelScope, which survives rotation.

lifecycleScope API: launch, launchWhen, and repeatOnLifecycle

The lifecycle library provides several ways to launch coroutines through lifecycleScope. Let’s look at the evolution of the API from deprecated methods to modern ones.

lifecycleScope.launch — Basic Launch

The simplest way is lifecycleScope.launch { ... }. The coroutine starts immediately and is cancelled at DESTROYED. However, it can execute code even when the UI is not visible (e.g., in the background after onStop). This is not always desirable.

Deprecated: launchWhenCreated / launchWhenStarted / launchWhenResumed

These methods paused the coroutine execution when the Lifecycle dropped below the specified state and resumed it upon return. However, they were marked as @Deprecated in lifecycle-runtime-ktx 2.6.0 because:

  • They did not cancel the coroutine — only paused it
  • They led to an accumulation of suspended coroutines consuming memory
  • They created race conditions during fast state switching

Modern API: repeatOnLifecycle

repeatOnLifecycle is Google’s recommended way to launch coroutines synchronized with the lifecycle. It cancels and restarts the coroutine every time the Lifecycle reaches the specified state.

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.uiState.collect { state ->
            updateUI(state)
        }
    }
}

The coroutine passed to repeatOnLifecycle starts when the Lifecycle reaches STARTED and cancels when it drops below STARTED. When it returns to STARTED, the coroutine restarts from scratch. This is safe and efficient — no coroutines are left suspended.

flowWithLifecycle — For Flow

For collecting data from Flow with lifecycle awareness, there is the flowWithLifecycle operator. It automatically stops and resumes collection when the Lifecycle state changes:

kotlin
viewModel.uiState
    .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
    .onEach { state -> updateUI(state) }
    .launchIn(lifecycleScope)

The flowWithLifecycle operator is the most concise way to safely subscribe to a Flow in the UI layer.

lifecycleScope Usage Examples

Let’s look at three real-world scenarios for using lifecycleScope in an Android application with Kotlin.

Example 1: Subscribing to Location Updates Only When the Screen Is Visible

kotlin
class MapFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                locationProvider.observeLocation().collect { loc ->
                    updateMapMarker(loc)
                }
            }
        }
    }
}

The coroutine starts when the fragment becomes visible (STARTED) and cancels when it leaves the screen (STOPPED). If the user switches to another app, Location updates do not drain the battery.

Example 2: Starting an Animation on Fragment Start

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.RESUMED) {
        animateFadeIn(titleView)
        delay(200)
        animateSlideUp(contentView)
    }
}

The animation runs only when the fragment is in the foreground (RESUMED). If the user minimizes the app during the animation, the coroutine is cancelled, and when they return, the animation starts over.

Example 3: Periodic Data Sync on a Visible Screen

kotlin
lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        while (isActive) {
            syncData()
            delay(30_000L)
        }
    }
}

Data is synchronized every 30 seconds, but only when the screen is visible. isActive checks whether the coroutine has been cancelled, providing a safe way to exit the loop when leaving the screen.

lifecycleScope vs viewModelScope: Use Cases

Both scopes are tied to the lifecycle, but to different aspects of it. Understanding the difference is critical for building a proper Android application architecture.

Key Difference

viewModelScope is tied to the ViewModel, which survives screen rotation. lifecycleScope is tied to the LifecycleOwner (Activity/Fragment), which is destroyed and recreated on rotation. This determines their use cases.

When to Use lifecycleScope

  • Subscribing to system events (Location, sensors, camera)
  • Animations and UI effects tied to a specific screen
  • Chunked data loading based on screen visibility
  • Operations that should stop when leaving the screen

When to Use viewModelScope

  • Loading data from a Repository
  • Business logic that should survive rotation
  • Caching and data processing
  • Any operation whose result is needed after rotation

Combined Usage

In practice, a combination of both scopes is common: viewModelScope loads data and manages state, while lifecycleScope subscribes to Flow from the ViewModel with lifecycle awareness. This separation of responsibilities is considered best practice in modern Android development.

Common Mistakes When Working with lifecycleScope

Let’s look at four of the most common mistakes developers make when using lifecycleScope.

Mistake 1: Using lifecycleScope Instead of viewModelScope for Data Loading

If you launch data loading in lifecycleScope.launch, the coroutine will be cancelled on screen rotation, and the data will have to be reloaded. Use viewModelScope for long-lived operations. lifecycleScope is only for UI-bound tasks.

Mistake 2: Collecting Flow Without repeatOnLifecycle

Directly calling viewModel.someFlow.collect { ... } inside lifecycleScope.launch continues collecting data even when the screen is not visible. This can lead to UI updates in the background and unnecessary overhead. Always use repeatOnLifecycle or flowWithLifecycle.

Mistake 3: Forgetting About Cancellation When Leaving the Screen

Although lifecycleScope is cancelled at DESTROYED, code after a suspend point may not execute on sudden cancellation. Do not rely on post-code execution after a suspend call unless you use NonCancellable.

Mistake 4: Using the Deprecated launchWhenStarted Instead of repeatOnLifecycle

launchWhenStarted and its counterparts do not cancel the coroutine, they only pause it. If the screen switches between foreground and background multiple times, the coroutine accumulates deferred calls. Switch to repeatOnLifecycle — this is the only correct way to synchronize with the Lifecycle.

Frequently Asked Questions

What is the difference between lifecycleScope and GlobalScope?

lifecycleScope is automatically cancelled when the LifecycleOwner is destroyed. GlobalScope lives for the entire duration of the application. A coroutine in lifecycleScope cannot update the UI after the component is destroyed, whereas in GlobalScope it can, leading to crashes. Always use lifecycleScope in the UI layer.

Can lifecycleScope be used in a ViewModel?

No, ViewModel is not a LifecycleOwner, so lifecycleScope is not available in it. ViewModel uses viewModelScope. If the code needs to run in both contexts, extract the logic into a use case or repository with suspend functions.

What happens when repeatOnLifecycle is called multiple times?

Each call to repeatOnLifecycle creates a new coroutine that launches the block when the specified Lifecycle state is reached. If repeatOnLifecycle is called twice for the same state, both blocks will run independently. Usually, one call in onViewCreated is sufficient.

Can I set a custom Dispatcher for lifecycleScope?

You cannot directly change the lifecycleScope dispatcher — it uses Dispatchers.Main.immediate. Inside the coroutine block, you can switch to another dispatcher using withContext. For tests, use TestDispatcher with LifecycleOwner.

Is lifecycleScope cancelled in onPause or onDestroy?

lifecycleScope is cancelled when the LifecycleOwner transitions to the DESTROYED state (after onDestroy). Simple lifecycleScope.launch calls are not cancelled in onPause or onStop. To pause when going to the background, use repeatOnLifecycle(STARTED) or repeatOnLifecycle(RESUMED).

Summary

  • lifecycleScope — a CoroutineScope tied to a LifecycleOwner and automatically cancelled at DESTROYED via LifecycleEventObserver
  • Dispatchers.Main.immediate — the default dispatcher, ensuring safe UI updates without unnecessary switching
  • repeatOnLifecycle — a modern API for launching coroutines at a specified Lifecycle state with automatic cancellation and restart
  • flowWithLifecycle — an operator for safe Flow collection from the UI with lifecycle awareness
  • launchWhenStarted is deprecated — instead of pausing, use repeatOnLifecycle, which cancels the coroutine rather than pausing it
  • lifecycleScope vs viewModelScope — lifecycleScope for UI operations (animations, Location), viewModelScope for data and business logic
  • Screen rotation — lifecycleScope is cancelled on rotation, viewModelScope survives; choose the scope based on the task

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also