Careeroza
CoroutineScope and CoroutineContext
Scope and Context
Every coroutine runs inside a CoroutineScope. A scope holds a CoroutineContext: a small map of elements that decide how the coroutine runs.
| Element | Key | Purpose |
|---|---|---|
Job | Job | lifecycle: active, cancelled, completed; parent-child links |
CoroutineDispatcher | ContinuationInterceptor | which thread(s) run the code |
CoroutineName | CoroutineName | name for debugging and logs |
CoroutineExceptionHandler | CoroutineExceptionHandler | last-resort handler for uncaught exceptions |
Combining Context Elements
Example
Context elements are combined with +. A child inherits the parent context and can override single elements.
import kotlinx.coroutines.*
fun main() = runBlocking(CoroutineName("parent")) {
println("Parent name: ${coroutineContext[CoroutineName]?.name}")
launch {
println("Child inherits: ${coroutineContext[CoroutineName]?.name}")
}.join()
launch(CoroutineName("child") + Dispatchers.Default) {
val thread = Thread.currentThread().name.substringBefore("-worker")
println("Child overrides: ${coroutineContext[CoroutineName]?.name} on $thread")
}.join()
val ctx = Dispatchers.IO + CoroutineName("io-task")
println("Context has a Job? ${ctx[Job] != null}")
println("Context name: ${ctx[CoroutineName]?.name}")
}Output
Parent name: parent Child inherits: parent Child overrides: child on DefaultDispatcher Context has a Job? false Context name: io-task
Scopes You Will Use
| Scope | Where | Cancelled when |
|---|---|---|
viewModelScope | Android ViewModel | ViewModel is cleared |
lifecycleScope | Activity / Fragment | lifecycle is destroyed |
rememberCoroutineScope() | Jetpack Compose | composable leaves the composition |
coroutineScope { } | inside suspend functions | block ends or fails |
CoroutineScope(SupervisorJob() + Dispatchers.Default) | your own long-lived classes | you call scope.cancel() |
GlobalScope | avoid | never (lives as long as the app) |