【问题标题】:Android: Await result of CallBack with Kotlin CoroutinesAndroid:使用 Kotlin 协程等待回调的结果
【发布时间】:2021-05-13 04:01:59
【问题描述】:

在我当前的项目中,我正在逐渐从 RXJava 过渡到 Coroutines。我有一种情况,我需要停止执行并等待回调返回的结果。我已通过以下方式将我的 RXJava 方法转换为使用协程:

   suspend fun fetchProducts(ids: List<String>) = suspendCoroutine<List<ProductItem>> { continuation ->
    val getProducts = repo.search(ids, null, null)
    getProducts.subscribe(
        { callResult ->
            productRequestInProgress.postValue(false)
            continuation.resume(callResult.result())
        },
        { error ->
            productRequestInProgress.postValue(false)
            //continuation.resumeWithException(t)
        }
    )

}

我正在从 .mapByPage 函数调用 fetchProducts 方法,但我收到消息 “暂停函数 'await' 只能从协程或其他暂停函数中调用” em> 。关于如何正确调用 fetchProducts 函数并等待 mapByPage 函数中的结果的任何想法?这是我收到错误消息的地方。谢谢

val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { hit ->
    Product(hit.json.getValue("id").jsonPrimitive.content)
}.mapByPage { it ->
    viewModelScope.launch {
       fetchProducts(it.mapNotNull { it.id })
    }.await()
}

【问题讨论】:

    标签: android kotlin kotlin-coroutines algolia


    【解决方案1】:

    您可以将协程包装在 runBlocking 块中。

    运行一个新的协程并中断当前线程直到 完成。
    ...
    它旨在将常规阻塞代码桥接到 以悬挂式编写的库

    .mapByPage { it ->
        runBlocking {
               fetchProducts(it.mapNotNull { it.id })
        }
    }
    

    【讨论】:

    • 我不完全确定您是否需要额外的 launch 功能。您还应该能够将所需的信息传递给 runBlocking 函数并直接在其中使用 async { }.await()。
    • 只是添加(以及其他任何偶然发现此问题的人),您无需使用额外的启动功能。我会编辑答案
    【解决方案2】:

    是的 await() 被定义为一个挂起函数,挂起关键字就像一个信号,表明这个函数是一个长时间运行的任务,因此应该异步运行,因为 await() 是一个挂起函数,如果我们被允许在没有的情况下执行它一个 couroutine 或另一个挂起函数,这意味着我们正在使用错误的运行任务进行阻塞调用,因此我们不允许这样做。

    所以可以从协程或其他挂起函数中调用挂起函数,这条规则保证挂起函数内部的长时间运行的任务不会阻塞主线程。

    另外你正在使用启动你应该使用async函数而不是launch启动是为了火而忘记工作,async用于完成后想要返回结果。

    通常,如果您的挂起函数具有返回类型,则使用 async 否则使用启动

    因为你想要一个 List 的产品回来你使用 async 如下。

    viewModelScope.launch{
    val products = viewModelScope.async(Dispathers.Default) { // Dispathers.Default is used for CPU intensive work, even if you don't pass anything Dispathers.Default is there , use Dispacther.IO for IO , Dispathers.Main for working with views in coroutine , like updating text view
       fetchProducts(it.mapNotNull { it.id })
    }.await()
    }
    

    【讨论】:

      猜你喜欢
      • 2021-01-27
      • 2022-01-18
      • 2020-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-22
      • 2019-02-21
      • 1970-01-01
      相关资源
      最近更新 更多