在Kotlin中处于suspendCoroutine时,AndroidNetworking从不返回

时间:2018-11-15 19:47:47

标签: 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,它会起作用,至少它会返回,但是await不会在corse上起作用,因为执行只会继续。

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

非常感谢!

3 个答案:

答案 0 :(得分:1)

好的,谢谢大家的帮助。 我将解释如何找到问题以及如何解决该问题。

在研究了有关回调和协程的更多信息之后,我决定像这样在回调过程中记录线程名称。 Log.d("TAG", "Execution thread: "+Thread.currentThread().name)

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

因此,协程中的代码在D/TAG: Execution thread: DefaultDispatcher-worker-1中运行,而回调在D/TAG: Execution thread: main上运行。

解决方案

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

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

  3. 使用suspendCoroutineresume()的{​​{1}}(感谢@Sergey)

示例

resumeWithException

答案 1 :(得分:0)

尝试这样的事情:

col1 = Table([[im]])
col2 = Table(data, repeatRows=1)
tblrow1 = Table([[col1, col2]], colWidths=None)
tblrow1.setStyle(
    TableStyle([
        ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
        ('VALIGN', (0, 0), (-1, -1), 'TOP'),
    ]))
elements.append(tblrow1)

答案 2 :(得分:0)

您的主要问题是您正在尝试使用runBlocking,这将取消您为项目引入异步网络库和协同程序所做的所有工作。如果您确实想在等待结果时进行阻止,则只需使用阻止网络调用即可。

如果您想继续使用异步网络操作,那么就不必考虑阻塞someFunction并直接在callGetSomething块中使用launch

override fun onSomeEvent(...) {
   this.launch {
     val result = callGetSomething(...)
     // use the result, you're on the GUI thread here
   }
}

以上内容假设您的thisActivityFragmentViewModel或实现CoroutineScope的类似对象。请参阅其documentation以了解如何实现。