这是关于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
在这里是什么意思?
答案 0 :(得分:1)
作为一般规则,如果您已经在协程环境中(在暂停功能中),则始终应优先考虑暂停而不是阻塞。正如您所指出的,这就是为什么在协程中不建议使用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
暂停而不是阻止答案 1 :(得分:0)
是的,这是错误的,因为它废除了协程必须提供的一切。这是一种更加复杂和混乱的书写方式
yourJavaExecutor.submit {
lifecycleState = LifecycleState.STARTED
cameraFacing = facing
openCamera()
}
换句话说,您什么也不做,只能将阻止任务提交给后台线程。