← All posts
Android11 June 20266 min read

Coroutine scopes, explained by where they die

Every scope question becomes easy once you ask what cancels it.

Every coroutine scope question becomes easy once you stop asking what it starts and start asking what cancels it.

Scopes are defined by their death

  • viewModelScope dies when the ViewModel clears
  • lifecycleScope dies with the lifecycle owner
  • A scope you built with CoroutineScope(...) dies when you remember to cancel it

That last one is where the leaks are.

The question to ask

Whatever work you are starting, ask what should stop it. A network call for a screen should stop when the screen goes. A file upload the user asked for probably should not.

// dies with the screen — right for a screen's data
viewModelScope.launch { repo.refresh() }

// outlives the screen — right for work the user committed to
applicationScope.launch { uploader.send(file) }

supervisorScope is about siblings

In a plain coroutineScope, one failing child cancels the rest. In a supervisorScope, the others carry on. Loading three independent sections of a screen wants supervision; three steps of one operation does not.

Collect with the lifecycle

collectAsStateWithLifecycle instead of collectAsState. Otherwise the flow keeps collecting behind a backgrounded screen, which is a battery bug that never shows up in testing.

Written by Sulton UzDev. Get new posts by email →

Sulton UzDev
Senior Android Developer · Kotlin, Compose & KMP · I build the app and its backend
© 2026 Sulton UzDevUzbekistanBlogProjectsAboutSubscribe