这是关于runBlocking的错误用法吗?
如“runBlocking”文档所说的This function should not be used from coroutine
。
此代码片段来自camerakit-android库。
fun start(facing: CameraFacing) {
GlobalScope.launch(cameraDispatcher) {
runBlocking {
lifecycleState = LifecycleState.STARTED
cameraFacing = facing
openCamera()
}
}
}
删除runBlocking后,它将无法工作。
那么
runBlocking
的含义是什么? 最佳答案
一般情况:使用coroutineScope代替runBlocking
作为一般规则,如果您已经在协程环境中(在暂停功能中),则始终应优先考虑暂停而不是阻塞。正如您所指出的,这就是在协程内部不鼓励使用runBlocking
的原因,因为它不必要地阻塞了当前线程。
因此,只要您觉得需要在挂起函数中使用runBlocking
,就应该使用 coroutineScope
代替。这是runBlocking
的暂停等效项,因为它在返回之前等待所有子协程完成执行:
fun start(facing: CameraFacing) {
GlobalScope.launch(cameraDispatcher) {
coroutineScope {
lifecycleState = LifecycleState.STARTED
cameraFacing = facing
openCamera()
}
}
}
您的情况:缺少结构化并发?
在您的特定情况下,由于您说没有
runBlocking
则“无法工作”,我怀疑openCamera()
会自行启动协程。启动协程的最佳实践是structured concurrency。这意味着将协程作为当前协程的子级启动,而不是使用
GlobalScope
来启动全局协程。如果
openCamera()
使用GlobalScope
启动协程,那么除非使用runBlocking
,否则您将无法等待其完成,因为即使coroutineScope
提供了作用域,调用GlobalScope.launch
时也不会使用该范围。只是要清楚,阻止您在此处使用
coroutineScope
(并迫使您使用runBlocking
)的原因不在GlobalScope.launch
内,而是调用了本身使用GlobalScope.launch
的函数(我怀疑openCamera()
在此执行此操作)。如果您真的想做正确的事情:
openCamera()
和start()
为CoroutineScope
的扩展名GlobalScope
用法,使用launch
,隐式接收器是您现在拥有的范围coroutineScope
而不是runBlocking
挂起而不是阻止