Can anyone explain the difference between them? I think scope provides a reference(e.g. Job) to cancel them and context provides a reference to underlying thread. Is that so?
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.
Kotlin coroutines provide an API that enables you to write asynchronous code. With Kotlin coroutines, you can define a CoroutineScope , which helps you to manage when your coroutines should run. Each asynchronous operation runs within a particular scope.
coroutines . To find a CoroutineName , we use just CoroutineName . This is not a type or a class: it is a companion object. It is a feature of Kotlin that a name of a class used by itself acts as a reference to its companion object, so ctx[CoroutineName] is just a shortcut to ctx[CoroutineName.
Scope in Kotlin's coroutines can be defined as the restrictions within which the Kotlin coroutines are being executed. Scopes help to predict the lifecycle of the coroutines.
They are indeed closely related. You might say that CoroutineScope
formalizes the way the CoroutineContext
is inherited.
CoroutineScope
has no data on its own, it just holds a CoroutineContext
. Its key role is as the implicit receiver of the block you pass to launch
, async
etc.
See this example:
runBlocking {
val scope0 = this
// scope0 is the top-level coroutine scope.
scope0.launch {
val scope1 = this
// scope1 inherits its context from scope0. It replaces the Job field
// with its own job, which is a child of the job in scope0.
// It retains the Dispatcher field so the launched coroutine uses
// the dispatcher created by runBlocking.
scope1.launch {
val scope2 = this
// scope2 inherits from scope1
}
}
}
You can see how the CoroutineScope
mediates the inheritance of coroutine contexts. If you cancel the job in scope1
, this will propagate to scope2
and will cancel the launch
ed job as well.
Note the key syntactical feature: I explicitly wrote scope0.launch
, but had I written just launch
, it would implicitly mean exactly the same thing. This is how CoroutineScope
helps to "automatically" propagate the scope.
Yes, in principle you are right, here more details.
Scope
viewModelScope
in Android) to avoid leakingContext
The context determines on which thread the coroutines will run. There are four options:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With