【问题标题】:Calling await() on suspend functions do not work correctly在挂起函数上调用 await() 无法正常工作
【发布时间】:2019-04-09 07:18:38
【问题描述】:
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 已经完成。我想确保它得到结果,然后以某种方式在其他请求中使用它。是因为我在那里使用了某种错误的调度程序还是什么?

【问题讨论】:

  • 能否添加您的 PortalApiClient 类代码?想看看你的返回对象是什么。
  • 在 test() 中我调用 apiClient - 获取数据并将返回的数据从 api 添加到局部变量。 Test() 什么都不返回。
  • 是的。我明白了,但是 apiclient 的返回对象是什么。是呼叫?
  • 这是一个回调。类型为 Response>,其中 Response 有“isSuccessful”、“error”,result 为泛型。

标签: android kotlin coroutine


【解决方案1】:

事情就是这样。当您通过 async 和 await 调用 test() 方法时,您所期望的是等待它完成。

但是由于您在测试方法中有一个回调流(apiclient 调用),它会在从服务器获得响应之前立即返回并退出测试方法。当响应准备好时,稍后会调用回调 lambda。此时运行阻塞已经完成。

所以你应该做的是将你的回调转换成协程。 Codelabs-example

您可以从 api 调用中创建一个 Deferred 对象列表并等待每个对象。

【讨论】:

    猜你喜欢
    • 2015-05-18
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多