CoroutineScope背后的概念是什么?

时间:2018-11-21 13:15:28

标签: kotlin kotlinx.coroutines

在阅读CoroutineScope的介绍和Javadoc之后,我仍然有点困惑CoroutineScope背后的想法是什么。

文档的第一句话“为新协程定义范围”。我不清楚:为什么我的协程需要一个瞄准镜?

此外,为什么不赞成使用独立的协程构建器?为什么这样做会更好:

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

代替

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

2 个答案:

答案 0 :(得分:5)

您仍然可以通过在GlobalScope中生成全局“独立”协程来使用它们:

GlobalScope.launch {
    println("I'm running unstructured")
}

但是,不建议这样做,因为在全局范围内创建协程与使用良好的旧线程基本相同。您创建了它们,但是以某种方式需要跟踪引用以稍后加入/取消它们。

使用结构化并发,即将协程嵌套在它们的作用域中,您将在总体上拥有一个更易于维护的系统。例如,如果您在另一个内部生成一个协程,则您将继承外部范围。这具有多个优点。如果取消外部协程,则取消将委派给内部协程。另外,您可以确保在所有子协程完成工作之前,外部协程不会完成。

CoroutineScope的{​​{3}}中也显示了一个很好的例子。

  

CoroutineScope应该在生命周期明确的实体上实施,这些实体负责启动子协程。在Android上此类实体的示例是Activity。

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

launch {
    produceSquares()
}

produceSquares内部创建的协程继承了launch的范围。您可以确定launchproduceSquares之前没有完成。另外,如果您取消了launch,这也会影响produceSquares

此外,您仍然可以像下面这样创建全局运行的协程:

GlobalScope.produceSquares()

但是,如上所述,在大多数情况下,这并不是最佳选择。

我也想推广我写的一篇文章。有一些示例说明了范围的含义:documentation

答案 1 :(得分:2)

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

  

On a more philosophical level,很少像线程那样“全局”启动协程。协程始终与应用程序中的某些本地范围相关,该局部范围是寿命有限的实体,例如UI元素。因此,对于结构化并发,我们现在需要在CoroutineScope中调用启动,CoroutineScope是由您生命周期有限的对象(如UI元素或其相应的视图模型)实现的接口。

这个概念的明显结果是:通过cancel定义scope的上下文,所有它的子协程也将被取消。