[英]Kotlin: Coroutines scope vs Coroutine context
Can anyone explain the difference between them?谁能解释一下它们之间的区别? I think scope provides a reference(eg Job) to cancel them and context provides a reference to underlying thread.
我认为 scope 提供了一个参考(例如 Job)来取消它们,而 context 提供了对底层线程的引用。 Is that so?
是这样吗?
They are indeed closely related.它们确实是密切相关的。 You might say that
CoroutineScope
formalizes the way the CoroutineContext
is inherited.你可能会说
CoroutineScope
形式化了CoroutineContext
的继承方式。
CoroutineScope
has no data on its own, it just holds a CoroutineContext
. CoroutineScope
本身没有数据,它只有一个CoroutineContext
。 Its key role is as the implicit receiver of the block you pass to launch
, async
etc.它的关键作用是作为传递给
launch
、 async
等的块的隐式接收器。
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.您可以看到
CoroutineScope
如何调解协程上下文的继承。 If you cancel the job in scope1
, this will propagate to scope2
and will cancel the launch
ed job as well.如果您取消
scope1
的作业,这将传播到scope2
并且也将取消launch
作业。
Note the key syntactical feature: I explicitly wrote scope0.launch
, but had I written just launch
, it would implicitly mean exactly the same thing.请注意关键的语法特征:我明确地编写了
scope0.launch
,但如果我只编写了launch
,它会隐含地表示完全相同的东西。 This is how CoroutineScope
helps to "automatically" propagate the scope.这就是
CoroutineScope
如何帮助“自动”传播范围。
Yes, in principle you are right, here more details.是的,原则上你是对的,这里有更多细节。
Scope范围
viewModelScope
in Android) to avoid leakingviewModelScope
)以避免泄漏的方法Context语境
The context determines on which thread the coroutines will run.上下文决定协程将在哪个线程上运行。 There are four options:
有四个选项:
Dispatchers.Default
- for CPU intense work (eg sorting a big list) Dispatchers.Default
- 用于 CPU 密集型工作(例如对大列表进行排序)Dispatchers.Main
- what this will be depends on what you've added to your programs runtime dependencies (eg kotlinx-coroutines-android
, for the UI thread in Android) Dispatchers.Main
- 这将取决于您添加到程序运行时依赖项中的内容(例如kotlinx-coroutines-android
,用于kotlinx-coroutines-android
中的 UI 线程)Dispatchers.Unconfined
- runs coroutines unconfined on no specific thread Dispatchers.Unconfined
- 在没有特定线程的情况下不受限制地运行协程Dispatchers.IO
- for heavy IO work (eg long-running database queries) Dispatchers.IO
- 用于繁重的 IO 工作(例如长时间运行的数据库查询) 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.
它创建了一个新的作用域,在该作用域中,协程将在指定用于 IO 工作的线程上运行(如果未更改),并通过其作用域取消它们。
val scope = CoroutineScope(context = Dispatchers.IO)
val job = scope.launch {
val result = suspendFunc1()
suspendFunc2(result)
}
// ...
scope.cancel() // suspendFunc1() and suspendFunc2() will be cancelled
CoroutineScope
has-a CoroutineContext
. CoroutineScope
有一个CoroutineContext
。
For example if you have:例如,如果您有:
runBlocking { // defines coroutineScope
launch(Dispatchers.Default) { //inherits coroutineScope but changes context
}
}
runBlocking
defines a CoroutineScope
(learn about it here ) which launch
inherits. runBlocking
定义了一个launch
继承的CoroutineScope
(在这里了解它)。 The context is being overridden by explicitly specifying a dispatcher here.通过在此处显式指定调度程序来覆盖上下文。 If you look at the definition of
launch
, you can see that it takes an optional CoroutineContext
:如果您查看
launch
的定义,您会发现它需要一个可选的CoroutineContext
:
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
...
)
Another part of the context would be the coroutine's name:上下文的另一部分是协程的名称:
launch(CoroutineName("launchMe") + Dispatchers.Default) {
println("")
}
Scope 范围
Every coroutine builder (like launch, async, etc) and every scoping function (like coroutineScope, withContext, etc) provides its own scope with its own Job instance into the inner block of code it runs.
每个协同程序构建器(如启动,异步等)和每个作用域函数(如coroutineScope,withContext等)都会将自己的作用域实例提供给它运行的内部代码块。 By convention, they all wait for all the coroutines inside their block to complete before completing themselves, thus enforcing the discipline of structured concurrency.
按照惯例,它们都会等待块内的所有协同程序在完成自己之前完成,从而强制执行结构化并发规则。
Context 上下文
Coroutines always execute in some context which is represented by the value of CoroutineContext type, defined in the Kotlin standard library.
协同程序总是在某些上下文中执行,该上下文由在Kotlin标准库中定义的CoroutineContext类型的值表示。
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, which is covered in this section.
主要元素是我们之前见过的coroutine的Job和它的调度程序,本节将对其进行介绍。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.