Вызов await() для функций приостановки работает неправильно

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 уже выполняется, когда это происходит. Я хотел бы убедиться, что он получит результат, а затем как-то использовать его в другом запросе. Это потому, что я использую какой-то неправильный диспетчер там или что?

не могли бы вы добавить код класса Portal ApiClient? хотите увидеть, что ваш возвращаемый объект.

rafa 09.04.2019 13:08

В test() я вызываю apiClient - получаю данные и добавляю возвращаемые данные из api в локальную переменную. Test() ничего не возвращает.

MaartinAndroid 09.04.2019 13:12

да. Я понял это, но что такое возвращаемый объект апиклиента. Звонок <>?

rafa 09.04.2019 13:40

Это обратный вызов. Тип — Response<List<Data>>, где Response имеет значение «isSuccessful», «error», а результат — общий тип.

MaartinAndroid 09.04.2019 13:43
2
4
252
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот в чем дело. То, что вы ожидаете, когда вы вызываете метод test() через асинхронный режим и ожидаете, - это дождаться его завершения.

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

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

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

Другие вопросы по теме