这两个功能有什么不同?
两者之间有两个主要区别:
- 用法不同:
suspend
型给人的感觉是同步的,而launch
型则是明显的异步型
- 第二个函数 destruct 了 struct 化并发,不应该以这种方式编写
让我详细说明一下.
从使用的Angular 来看,suspend
函数看起来是同步的:当您调用它时,下一行代码仅在函数完成时执行(与任何其他常规函数一样).这使得推理变得很容易.您甚至可以将suspend
函数的返回值赋给一个变量,然后继续您的生活,就像该函数不是suspend
一样.当然,当你已经处于suspend
的上下文中时.如果不是,则必须使用显式的协程构建器(如launch
、async
或runBlocking
)启动"根"协程.
当使用launch
时,您显式地启动了一个异步任务,因此launch
之后的代码与launch
中的代码并发运行.因此,反过来,当调用doSomething1()
时,它之后的代码将与内部launch
中的任何内容并发运行.然而,从API的Angular 来看,确实不清楚该函数是否会启动比它更持久的任务.这也符合这样一个事实,即您不应该创建这样的"免费"协程作用域.我将在下面详细说明.
什么时候用第一个例子,什么时候用第二个例子?
尽可能多地使用suspend
个函数以使事情变得简单.在大多数情况下,您不需要启动比函数调用持续时间更长的任务,因此这是非常好的.通过使用coroutineScope { ... }
启动一些协程,您仍然可以并发地执行一些工作inside your suspend function.这不需要外部提供的作用域,而且从调用者的Angular 来看,所有计算都将在Suspend函数调用中进行,因为coroutineScope {}
将等待子协程完成,然后才返回.
这里使用launch
的函数的行为非常糟糕,你永远不应该写这样的东西:
- 不应该当场制造
CoroutineScope
个,然后留在那里等死.你应该控制它,并在适当的时候取消它
- 如果在调用此函数时已处于挂起状态,则现有的协程上下文和作业(job)将被忽略
为了避免这些问题,您可以通过将CoroutineScope
设置为接收器而不是现场创建接收器来显式地使用API:
private fun CoroutineScope.doSomething1() {
launch(Dispatchers.IO) {
//do something
}
}
但只有在函数的本质是启动在函数返回后继续运行的东西时,才使用这种方法.