Вызов await () для функций приостановки работает неправильно - PullRequest
2 голосов
/ 09 апреля 2019
private val coroutineSupervisor = SupervisorJob()
protected val dispatcherProvider = CoroutineDispatcherProvider()
protected val viewModelScope = CoroutineScope(dispatcherProvider.main + coroutineSupervisor)

class CoroutineDispatcherProvider {

    val main: CoroutineDispatcher
        get() = Dispatchers.Main

    val background: CoroutineDispatcher
        get() = Dispatchers.IO
}

viewModelScope.launch {
    ...
    runBlocking {
        async { firstNumber() }.await()
        async { secondNumber() }.await()
        async { test() }.await()
        async { thirdNumber() }.await()
    }
}

suspend fun firstNumber(): Int {
    delay(3_000) // 3 seconds delay
    return 5
}
suspend fun secondNumber(): Int {
    delay(5_000) // 5 seconds delay
    return 8
}
suspend fun thirdNumber(): Int {
    delay(7_000) // 7 seconds delay
    return 10
}

suspend fun test() {
    withContext(dispatcherProvider.background) {
        ...
    }
}

Начал изучать сопрограммы несколько дней назад, и я увидел что-то странное.Функции firstNumber, secondNumber и thirdNumber выполняются как следует - задержка завершается, а затем выполняется следующая функция - в правильной последовательности, а test () - нет.Это возвращает значение намного позже, и runBlocking уже сделан, когда это произойдет.Я хотел бы убедиться, что он получит результат, а затем каким-то образом использовать его в другом запросе.Это потому, что я там использую какой-то неправильный диспетчер или как?

1 Ответ

1 голос
/ 09 апреля 2019

Вот эта вещь.То, что вы ожидаете, когда вызываете метод test () с помощью async и await, - это дождитесь его завершения.

Но поскольку у вас есть поток обратного вызова (apiclient call) внутри метода test, он возвращается сразу перед получением ответас сервера и выходит из теста методом.Позже обратный вызов лямбда вызывается, когда ответ готов.К этому времени блокировка запуска уже сделана.

Итак, вам нужно преобразовать ваш обратный вызов в сопрограмму. Codelabs-example

И вы можете создать список отложенных объектов из вызова API и ожидать каждого из них.

...