What happens to viewModelScope work on rotation?

Coroutines Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Predict the output

The request takes 3 seconds. The user rotates after 1 second. What happens to the request?

class ProfileViewModel(private val repo: UserRepository) : ViewModel() {
    val user = MutableStateFlow<User?>(null)

    init {
        viewModelScope.launch {
            user.value = repo.user("42")   // takes about 3 s
        }
    }
}
Options
Hint 1 of 2

Is the ViewModel recreated on rotation?

Hint 2 of 2

When does viewModelScope get cancelled?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A It keeps running and the recreated screen shows the user

Correct. The ViewModel outlives the configuration change, so its scope is not cancelled.

Why not the others?
  • B It is cancelled, and a new request starts when the Activity is recreated. That is what happens with lifecycleScope, which is tied to one Activity instance.
  • C It finishes, but the result is lost because the old Activity is gone. The result lands in the ViewModel's StateFlow; the new Activity collects it.
  • D The app crashes because the Activity it belongs to was destroyed. The coroutine holds no reference to the Activity, so nothing leaks or crashes.
Two scenarios for one screen: rotate, then press Back. A grid shows which kinds of state keep their value.

Illustrative, based on Compose and Android rules; not a device recording

Text version

Rotate

  1. A onPause
  2. A onStop
  3. A onDestroy
  4. A' onCreate
  5. A' onStart
  6. A' onResume

Press Back

  1. A onPause
  2. A onStop
  3. A onDestroy
  4. A ViewModel.onCleared
What survives
StateRotatePress Back
local var✕ lost✕ lost
remember✕ lost✕ lost
rememberSaveable✓ kept✕ lost
ViewModel✓ kept✕ lost
SavedStateHandle✓ kept✕ lost
Room / disk✓ kept✓ kept

30-second answer

Rotation keeps the request running. The Activity is destroyed and recreated, but its ViewModel survives the configuration change, so viewModelScope is not cancelled and the new screen gets the result. Pressing Back finishes the Activity for good: the ViewModel is cleared and viewModelScope cancels the call.

Practise saying it · 45 s. No recording, just a timer

Explain what survives rotation and what cancels viewModelScope.

Say your answer out loud, then check which of these points you covered:

  • The ViewModel survives configuration changes
  • viewModelScope is cancelled when the ViewModel is cleared, when the screen finishes
  • lifecycleScope is cancelled on rotation
  • Process death keeps only SavedStateHandle and disk

Deep dive

viewModelScope is cancelled when the ViewModel is cleared (just before onCleared() runs), which happens only when the owner is gone for good (finished, or its back-stack entry popped), not on a configuration change.

The new Activity instance gets the same ViewModel from the ViewModelStore, so collecting its StateFlow shows the result as soon as it lands.

Process death is different: the whole process is killed, the ViewModel goes with it, and only SavedStateHandle and disk survive.

Work in lifecycleScope is tied to the Activity instance, so it is cancelled on rotation. That is why screen-level loading belongs in the ViewModel.

Common mistakes

  • Saying the ViewModel is recreated on rotation.
  • Launching loading work in lifecycleScope and then wondering why it restarts on every rotation.
  • Assuming the ViewModel survives process death.

Senior take & follow-ups

Say which owner each scope belongs to. Interviewers want to hear that a scope's lifetime decides what survives, and that rotation, finishing and process death are three different events.

Follow-up questions

Think of your answer first, then open the hint.

  1. Where would you put work that must finish even if the user leaves the screen?

    Show hint

    WorkManager, or an application-scoped CoroutineScope for short work.

  2. How does the screen get the result after rotation?

    Show hint

    It collects a StateFlow held by the ViewModel; the latest value is replayed.

Similar on iOS: @MainActor view models iOS has no configuration-change recreation; the view model's lifetime is owned by SwiftUI state instead.

Suggest a fix if something here is wrong or out of date.