AndroidNetworking 在 Kotlin 中的 suspendCoroutine 中永远不会返回

标签 android kotlin coroutine kotlinx.coroutines

我正在尝试新的协程,并尝试将它们合并到具有一些丑陋的 AndroidNetworking api 请求的现有项目中。

所以我当前的 api 请求正在使用这样的回调...

fun getSomethingFromBackend(callback: (response: JSONArray?, error: String?) -> Unit) {
  AndroidNetworking.get(...).build().getAsJSONObject(object : JSONObjectRequestListener {
    override fun onResponse(response: JSONObject) { ... }
    override fun onError(error: ANError) { ... }
  }
}

现在我正在尝试合并这样的协程......

fun someFunction() = runBlocking {
  async { callGetSomething() }.await()
}

suspend fun callGetSomething(): JSONObject? = suspendCoroutine {
  Something().getSomethingFromBackend {something
    ...
    it.resume(something)
  }
}

正如您所看到的,我正在尝试在协程中运行 callGetSomething,一旦到达那里,就挂起协程,直到异步 API 返回。

我的问题是,它永远不会返回。即使我在 onResponseonError 等中调试,它也永远不会从后端返回。

但是,如果我删除 = suspendCoroutine 它会起作用,至少它会返回,但等待不会在 corse 中起作用,因为执行将继续。

如何解决这个问题,以便 await() 实际上等待异步调用回调?

非常感谢!

最佳答案

好的,谢谢大家的帮助。 我将解释我如何发现问题以及如何解决它。

在研究了有关回调和协程的更多信息后,我决定在回调期间记录线程名称,如下所示。 Log.d("TAG", "执行线程: "+Thread.currentThread().name).

这让我意识到所有回调(错误和成功)实际上都在主线程上运行,而不是在我为其设置的协程上运行。

因此,我的协程中的代码在 D/TAG: 执行线程:DefaultDispatcher-worker-1 中运行,但回调在 D/TAG: 执行线程:main 上运行.

解决方案

  1. 避免 runBlocking:这会阻塞主线程,在这种情况下,这就是回调永远不会返回的原因。

  2. 启动协程时使用 Dispatchers.Main,这样我实际上可以在 UI 中使用返回的值。

  3. 使用suspendCoroutine及其resume()resumeWithException(感谢@Sergey)

示例

fun someFunction() {
  GlobalScope.launch(Dispatchers.Main) {
    result = GlobalScope.async { callGetSomething() }.await()
    ...
  }
}

suspend fun callGetSomething(): JSONObject? = suspendCoroutine {
  Something().getSomethingFromBackend {something
    ...
    it.resume(something)
  }
}

关于AndroidNetworking 在 Kotlin 中的 suspendCoroutine 中永远不会返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53326917/

相关文章:

android - 将属性添加到列表时为 "Attempt to write to null array"

android - CameraX 相机加载速度慢

android - HTML 中的可滚动内容不会在 Android 模拟器或手机中滚动

带有导航组件的 Android 深层链接无法按预期工作

android - 是否可以在数据类 kotlin android 中使用不同类和数据类型的相同键?

swift - 在 Swift 中编写 Kotlin 的 by-clause(又名类委托(delegate))的正确方法是什么?

python - 为什么我们需要 python 中的协程?

javascript - 基于生成器的Javascript协程库,支持Chrome浏览器

android - e:无法解析以下类的父类(super class)型。请确保您在类路径中具有必需的依赖项:

c++ - 无堆栈协程与有堆栈协程有何不同?