Kotlin 在CoroutineScope和launch中,作为争论的不同工作是什么?

Kotlin 在CoroutineScope和launch中,作为争论的不同工作是什么?,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,这两个代码运行完全相同。将作业放入CoroutineScope和启动有什么不同 private val job = CoroutineScope(Dispatchers.Main).launch(start = CoroutineStart.LAZY) { for(i in 10 downTo 0) { Log.d("test", ": $i") delay(1000) } } CoroutineScope

这两个代码运行完全相同。将作业放入CoroutineScope和启动有什么不同

private val job = CoroutineScope(Dispatchers.Main).launch(start = CoroutineStart.LAZY) {
    for(i in 10 downTo 0) {
        Log.d("test", ": $i")
        delay(1000)
    }
}

CoroutineScope(Dispatchers.Main+job).launch{ }

CoroutineScope(Dispatchers.Main).launch(job) { }

从源代码的角度看,两者似乎没有太多区别。
operator fun plus

返回包含此上下文中的元素和元素的上下文 从其他方面来看。此上下文中具有相同键的元素 正如在另一个是下降

这就解释了你第一次测试的工作原理。第二,使用上下文参数调用
launch
,调用

为新的协同程序创建上下文。它安装 Dispatchers。没有其他dispatcher或 已指定ContinuationInterceptor,并添加对的可选支持 调试工具(打开时)

看看它的源代码:

public-CoroutineScope.newCoroutineContext(上下文:CoroutineContext):CoroutineContext{
val组合=coroutineContext+上下文
val debug=if(debug)combined+CoroutineId(COROUTINE_ID.incrementAndGet())else combined
返回if(组合!==Dispatchers.Default&&combined[ContinuationInterceptor]==null)
调试+分派器。默认为else调试
}
我们可以看到,它最终也使用了
操作符fun plus


这里还提到了一些其他的差异,这些差异似乎可以忽略,但最终在您的两个测试中启动的协同程序的上下文看起来是相同的。

从技术上讲,两者都会导致相同的行为,但主要的一点是,两者都不是使用
CoroutineScope()
工厂的好方法。这是写同样东西的惯用方式:

GlobalScope.launch(Dispatchers.Main+job) { ... }
如果这让你大吃一惊(“不要使用GlobalScope!”),那是因为它应该——你的示例只是犯同样错误的另一种方式,代码更加冗长。您构建了一个
CoroutineScope
,但没有对其进行引用,从而产生了与
GlobalScope
单例完全相同的无界且不可取消的作用域


此外,使用作为实际协同路由句柄的
作业
实例的方式也是错误的:与协同路由作用域关联的作业应该是从
Job()
SupervisorJob()
返回的独立实例。其唯一目的是作为取消整个范围或检查其状态的中心点。

谢谢您的建议!如果你不介意的话,你能给我一个使用作业的示例代码吗?类似于从Job()或SupervisorJob()返回的。类似于
val rootScope=CoroutineScope(Dispatchers.Main+Job())
,这相当于较短的
CoroutineScope(Dispatchers.Main)
,因为如果缺少它将添加
Job()
。然后,如果要取消工作,请使用
rootScope.coroutineContext.job.cancel()