我经常创建具有包含协程的函数的类。并不总是清楚该函数是否正在被某个绑定(bind)到 UI 的组件使用,或者是否正在执行更面向 IO 的后台工作。这是一个例子:
fun myFunction() {
GlobalScope.launch {
// Do something
}
}
在此示例中,未指定 Dispatcher.MAIN 或 Dispatchers.IO。这是执行此操作的正确方法吗?协程是否使用调用客户端正在使用的范围?当我明确知道我需要特定范围时,我是否应该只指定调度程序?
最佳答案
GlobalScope
将协程的生命周期绑定(bind)到应用程序本身的生命周期。
这意味着从此范围启动的协程将继续存在,直到发生以下两件事之一
- 协程完成其工作。
- 应用程序本身被终止。
强烈建议不要在 GlobalScope 实例上使用异步或启动。
No Dispatcher.MAIN or Dispatchers.IO is specified. Is this the correct way to do this?
是啊,为什么不呢?如果协程内的工作与 UI 或 IO 无关,那就去做吧。
Should I only specify a dispatcher when I know definitively that I need a specific scope?
为了回答这个问题,我们首先看看文档中 launch
的定义,
fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit ): Job (source)
我们正在讨论的Dispatcher
是一种CoroutineContext
。正如您在定义中看到的,如果没有提到 CoroutineContext
(这意味着我们也没有提到 Dispatcher
),它默认设置为 EmptyCoroutineContext
code> 内部使用 Dispatchers.Default ,这就是文档所说的,
The default CoroutineDispatcher that is used by all standard builders like launch, async, etc if neither a dispatcher nor any other ContinuationInterceptor is specified in their context.
It is backed by a shared pool of threads on JVM. By default, the maximum number of threads used by this dispatcher is equal to the number of CPU cores, but is at least two.
因此,即使您忘记提及调度程序,调度程序也会从池中随机选择任何可用线程并将其交给协程。但请确保在未提及 Dispatcher 的情况下不要启动任何 UI
相关工作。
关于kotlin - 何时为类中的协程指定 Dispatchers.xxx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59715510/