CoroutineScope groups jobs beneath an owner. GlobalScope has application-process lifetime and no natural cancellation point, so it is rarely correct for user-initiated Android work.
Practical guidance
- Tie screen work to viewModelScope or lifecycleScope.
- Inject an application scope for work that must outlive a screen.
- Give custom scopes a SupervisorJob and an explicit close or shutdown path.
- Use WorkManager for guaranteed deferrable work.
Working example
class SyncManager(
private val repository: SyncRepository,
private val appScope: CoroutineScope
) {
fun schedule() = appScope.launch { repository.sync() }
}
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
Common mistakes
- GlobalScope jobs continue after navigation and can update stale state.
- A custom scope without cancellation is merely a renamed global scope.
- Process death still stops application-scoped coroutines.
Key takeaway
Choose the shortest lifetime that satisfies the requirement. For durable background work, a coroutine alone is not a scheduler.
