试着深入到合作中去。我有一个suspendCancellableCoroutine,它应该获取一个网络响应。我从查尔斯身上可以看出,网络呼叫已被发送并成功返回。然而,我的应用程序只是挂在网络请求线上。
private suspend fun fetchVisualElementsFromServer(clubId: String): VisualElements {
return suspendCancellableCoroutine { cont ->
visualElementsService.fetchVisualElementsForClub(clubId)
.enqueue(object : Callback<ResultVisualElements> {
override fun onResponse(
call: Call<ResultVisualElements>,
response: Response<ResultVisualElements>
) {
if (response.isSuccessful) {
response.body()?.let {
if (it.result == RESULT_SUCCESS) {
saveVisualElementsResponseInSharedPreferences(it.visual_elements)
cont.resume (it.visual_elements)
} else {
cont.cancel() //edit
}
} ?: cont.cancel() //edit
} else {
cont.cancel(IOException("${response.code()}: ${response.errorBody()}"))
}
}
override fun onFailure(call: Call<ResultVisualElements>, t: Throwable) {
Timber.e(t, "visual elements fetch failed")
cont.cancel() // edit
}
})
}
}它挂在这里:
VisualElementsService.kt
fun fetchVisualElementsForClub(clubId: String): Call<ResultVisualElements> {
return dataFetcherService.getVisualElementsForClub(clubId)
}我在这里错过了什么?我试图使fetchVisualElementsForClub()成为一个挂起函数,但这只会使suspendCancellableCoroutine抛出一个Suspension functions can only be called within coroutine body错误。但我以为他的身体还在体内?
任何帮助都很感激。谢谢。
编辑
下面我对Rene的回答作出回应,我想补充几点。
您说得对,我错过了三个cont.cancel()调用。我修改了OP。好点子。
我在整个suspendCancellableCoroutine中都有断点,因此任何可能的场景(成功、失败等)都是如此。会被击中的。但那回拨从来没有登记过。
想知道fetchVisualElementsForClub()中是否缺少什么东西来将回调传递给suspendCancellableCoroutine。这似乎是挂在这里的。
发布于 2019-10-13 09:54:13
必须在回调处理中的每个分支上调用cont.resume()或cont.cancel()。但在你的例子中,至少有三起案件失踪。
it.result不是您调用的RESULT_SUCCESS;onFailure中有问题,则什么也不调用。H 211G 212只要不调用resume或cancel,协同线就会保持挂起,这意味着挂起。
发布于 2019-10-13 04:07:21
当您使用挂起关键字时,您正在告诉该函数应该在coroutine中调用,例如:
suspend fun abc(){
return
}当您想调用上面的函数时,您必须在协同线中调用它,如下所示:
GlobalScope.launch {
abc()
}https://stackoverflow.com/questions/58360319
复制相似问题