Общий случай: используйте coroutineScope вместо runBlocking
Как правило, если вы уже находитесь в контексте сопрограммы (в функции приостановки), вы всегда должны отдавать предпочтение приостановке, а не блокированию.Вот почему, как вы заметили, использование runBlocking
не рекомендуется из-за сопрограмм, потому что оно неоправданно блокирует текущий поток.
Таким образом, каждый раз, когда вы чувствуете, что вам нужно runBlocking
внутри функции приостановки, вы должныиспользуйте взамен coroutineScope
.Это эквивалент приостановки runBlocking
, поскольку он ожидает, пока все дочерние сопрограммы завершат свое выполнение, прежде чем вернуть:
fun start(facing: CameraFacing) {
GlobalScope.launch(cameraDispatcher) {
coroutineScope {
lifecycleState = LifecycleState.STARTED
cameraFacing = facing
openCamera()
}
}
}
Ваш случай: отсутствует структурированный параллелизм?
В вашем конкретном случае,так как вы говорите, что «не может работать» без runBlocking
, я подозреваю, что openCamera()
запускает сопрограммы самостоятельно.
Лучшей практикой для запуска сопрограмм является структурированный параллелизм .Это означает запуск сопрограмм в качестве дочерних элементов текущей сопрограммы вместо запуска глобальных сопрограмм с GlobalScope
.
Если openCamera()
использует GlobalScope
для запуска сопрограммы, вы не сможете ждать еезавершить, если не использовать runBlocking
, потому что даже если coroutineScope
предоставляет область, он не будет использоваться при вызове GlobalScope.launch
.
Просто чтобы было ясно, что мешает вам использовать coroutineScope
здесь(и заставляет вас использовать runBlocking
) - это не внутри a GlobalScope.launch
, а вызов функции, которая сама использует GlobalScope.launch
(я подозреваю, что openCamera()
делает это здесь).
Если вы действительно хотите сделать все правильно:
- объявите
openCamera()
и start()
как расширения CoroutineScope
- удалить все
GlobalScope
использования, используйтеlaunch
с неявным получателем, являющимся областью, которую вы теперь имеете - , используйте
coroutineScope
вместо runBlocking
для приостановки вместо блокировки