Yes, in principle you are right, here more details.
Scope
- a coroutine must run in a scope
- it is a way to keep track of all coroutines that run in it
- all (cooperative) coroutines can be cancelled via their scope
- scopes get uncaught exceptions
- they are a way to bind coroutines to an application specific lifecycle (e.g.
viewModelScope
in Android) to avoid leaking
Context
The coroutine context is a set of various elements. The main elements
are the Job of the coroutine, which we’ve seen before, and its
dispatcher […]. (Source)
In case you specify a dispatcher there are four options which basically determine on which thread the coroutines will run:
Dispatchers.Default
– for CPU intense work (e.g. sorting a big list)Dispatchers.Main
– what this will be depends on what you’ve added to your programs runtime dependencies (e.g.kotlinx-coroutines-android
, for the UI thread in Android)Dispatchers.Unconfined
– runs coroutines unconfined on no specific threadDispatchers.IO
– for heavy IO work (e.g. long-running database queries)
The following example brings both scope and context together. It creates a new scope in which the coroutines will run (if not changed) on a thread designated for IO work and cancels them via their scope.
val scope = CoroutineScope(context = Dispatchers.IO)
val job = scope.launch {
val result = suspendFunc1()
suspendFunc2(result)
}
// ...
scope.cancel() // suspendFunc1() and suspendFunc2() will be cancelled