我有点困惑,我知道如果一个函数要使用协程,它应该声明为suspend。例如:
private suspend fun doSomething() {
withContext(Dispatchers.IO) {
//do something
} }
而且我还知道有这样一种方法可以使用协程而不需要挂起函数。
private fun doSomething1() {
CoroutineScope(Dispatchers.IO).launch {
//do something
} }
这两个函数有什么区别?什么时候用第一个例子,什么时候用第二个例子?
2条答案
按热度按时间0h4hbjxa1#
这两种功能有什么区别?
两者之间有2个主要区别:
suspend
"感觉"同步,而launch
显式异步让我详细说明一下。
从使用Angular 来看,
suspend
函数似乎是同步的:当您调用它时,下一行代码仅在函数完成时执行(就像任何其他常规函数一样)。这使得推理变得容易。你甚至可以将suspend
函数的返回值赋给一个变量,然后继续你的生活,就好像这个函数不是suspend
一样。也就是说,当你已经在一个suspend
的上下文中时,你必须用一个显式的协程构建器(比如launch
,async
或runBlocking
)来启动"根"协程。当使用
launch
时,您显式启动了一个异步任务,因此launch
之后的代码将与launch
内部的代码并发运行。因此,当调用doSomething1()
时,它之后的代码将与launch
内部的代码并发运行。然而,从API的Angular 来看,这个函数是否会启动一个比它更有效的任务还不清楚。这也与你不应该创建这样的"自由"协同程序作用域的事实有关。我将在下面详细说明。什么时候用第一个例子,什么时候用第二个例子?
尽可能多地使用
suspend
函数来简化事情。大多数时候,你不需要启动比函数调用更有效的任务,所以这是非常好的。你仍然可以通过使用coroutineScope { ... }
启动一些协程来并发地 * 在你的suspend函数内 * 做一些工作。这不需要外部提供的作用域,从调用者的Angular 来看,所有的计算都将发生在suspend函数调用中,因为coroutineScope {}
将等待子协程完成后再返回。这里使用
launch
的函数表现很差,你不应该这样写:CoroutineScope
不应当场创建并任其自生自灭,应保留一个句柄并在适当时取消为了避免这些问题,您可以通过将
CoroutineScope
设置为接收器而不是立即创建一个接收器来使API显式化:但是,只有当函数的本质是启动一些在函数返回后仍将继续的东西时,才使用这种方法。
5gfr0r5j2#
最简单的答案是suspend函数是一个可以在CoroutineScope中执行的块。所以它不是第一个例子和第二个例子。通过组合这些块,您可以启动自己的作用域,并使用不同的上下文执行suspend函数。
编辑:这只是一个简单的基本示例,它没有处理协程作用域的正确生命周期,不应该直接使用。