сопрограммы kotlin: запуск блокировки в kotlin global.launch - PullRequest
2 голосов
/ 16 мая 2019

это неправильное использование в 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? 1010 *

Ответы [ 2 ]

1 голос
/ 16 мая 2019

Общий случай: используйте 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 для приостановки вместо блокировки
0 голосов
/ 17 мая 2019

Да, это неправильно, потому что оно аннулирует все, что сопрограммы могут предложить. Это более сложный и грязный способ написания

yourJavaExecutor.submit {
    lifecycleState = LifecycleState.STARTED
    cameraFacing = facing
    openCamera()
}

Другими словами, вы ничего не делаете, но отправляете задачу блокировки в фоновый поток.

...