什么是CoroutineScope背后的概念?

mor*_*s05 10 kotlin kotlinx.coroutines

在阅读了CoroutineScope的介绍和javadoc后,我仍然有点混淆了背后的想法CoroutineScope是什么.

文档的第一句"定义新协程的范围".我不清楚:为什么我的协同程序需要一个范围?

另外,为什么单独的协同构建器被弃用?为什么这样做更好:

fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
    for (x in 1..5) send(x * x)
}
Run Code Online (Sandbox Code Playgroud)

代替

fun produceSquares(): ReceiveChannel<Int> = produce { //no longer an extension function
    for (x in 1..5) send(x * x)
}
Run Code Online (Sandbox Code Playgroud)

s1m*_*nw1 6

您仍然可以使用全局"独立"协同程序来生成它们GlobalScope:

GlobalScope.launch {
    println("I'm running unstructured")
}
Run Code Online (Sandbox Code Playgroud)

但是,不建议这样做,因为在全局范围内创建协同程序与使用旧的线程基本相同.你创建它们但不知何故需要跟踪引用以便以后加入/取消它们.

使用结构化并发,即在其作用域中嵌套协同程序,您将拥有一个更易于维护的系统.例如,如果在另一个中生成一个协同程序,则继承外部作用域.这有许多优点.如果取消外部协程,取消将被委托给其内部协程.此外,您可以确保在其所有子协同程序完成其工作之前,外部协程将无法完成.

另外还有中显示了很好的示范文档CoroutineScope.

CoroutineScope应该在具有明确定义的生命周期的实体上实现,这些实体负责启动子协同程序.Android上的此类实体的示例是Activity.

毕竟,显示的produceSquares方法的第一个版本更好,因为它只在a中调用时才可执行CoroutineScope.这意味着你可以在任何其他协程中运行它:

launch {
    produceSquares()
}
Run Code Online (Sandbox Code Playgroud)

内部创建的协produceSquares程继承了范围launch.你可以肯定launch之前没有完成produceSquares.此外,如果您取消launch,这也会产生影响produceSquares.

此外,您仍然可以创建一个全局运行的协同程序,如下所示:

GlobalScope.produceSquares()
Run Code Online (Sandbox Code Playgroud)

但是,如上所述,在大多数情况下,这不是最好的选择.

我也想宣传我写的一篇文章.有一些示例证明了范围的含义:https://kotlinexpertise.com/kotlin-coroutines-concurrency/


And*_*nin 4

它与结构化并发的概念相关,结构化并发定义了协程之间的结构。

\n\n
\n

在更哲学的层面上,你很少像使用线程一样启动协程\xe2\x80\x9cglobally\xe2\x80\x9d。协程始终与应用程序中的某些本地范围相关,这是一个具有有限生命周期的实体,例如 UI 元素。因此,通过结构化并发,我们现在要求在 CoroutineScope 中调用 launch,它是由生命周期有限的对象(例如 UI 元素或其相应的视图模型)实现的接口。

\n
\n\n

作为这个概念的一个明显的结果:通过cancelling a 的上下文scope,它的所有子协程也将被取消。

\n