[英]Suspend Coroutine Hangs
Trying to get a deeper into coroutines.试图更深入地了解协程。 I have a
suspendCancellableCoroutine
that is supposed to fetch a network response.我有一个应该获取网络响应的
suspendCancellableCoroutine
。 I can see in Charles that the network call is dispatched and returns successfully.我可以在 Charles 中看到网络调用已发送并成功返回。 However, my app just hangs on the network request line.
但是,我的应用程序只是挂在网络请求线上。
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
}
})
}
}
This where it hangs:这是它挂起的地方:
VisualElementsService.kt视觉元素服务.kt
fun fetchVisualElementsForClub(clubId: String): Call<ResultVisualElements> {
return dataFetcherService.getVisualElementsForClub(clubId)
}
What am I missing here?我在这里想念什么? I tried to make the
fetchVisualElementsForClub()
a suspend function, but that just makes the suspendCancellableCoroutine
throw a Suspension functions can only be called within coroutine body
error.我试图使
fetchVisualElementsForClub()
成为暂停 function,但这只会使suspendCancellableCoroutine
抛出一个Suspension functions can only be called within coroutine body
。 But I thought that his was within a coroutine body?但我以为他在协程体内?
Any help appreciated.任何帮助表示赞赏。 Thanks.
谢谢。
EDIT编辑
I response to Rene's answer below, I want to add a few things.我在下面回复 Rene 的回答,我想补充一些东西。
You are right, I am missing three cont.cancel() calls.你是对的,我错过了三个 cont.cancel() 电话。 I've modified the OP.
我已经修改了OP。 Good points.
好点。
I have breakpoints all over the suspendCancellableCoroutine
such that any possible scenario (success, failure, etc.) will be hit.我在
suspendCancellableCoroutine
都有断点,这样任何可能的情况(成功、失败等)都会受到影响。 But that callback never registers.但该回调从未注册。
Wondering if there is something missing in fetchVisualElementsForClub()
that is needed to pass the callback up to the suspendCancellableCoroutine
.想知道
fetchVisualElementsForClub()
中是否缺少将回调传递给suspendCancellableCoroutine
所需的东西。 That seems to be where this is hanging.这似乎是悬挂的地方。
You must call cont.resume()
or cont.cancel()
on every branch in your callback handling.您必须在回调处理中的每个分支上调用
cont.resume()
或cont.cancel()
。 But in your example at least three cases are missing.但是在您的示例中,至少缺少三种情况。
it.result
is not RESULT_SUCCESS
you call nothing.it.result
不是RESULT_SUCCESS
你什么都不叫。onFailure
, you call nothing.onFailure
出现问题,你什么也不叫。 As long as neither resume
or cancel
is invoked, the coroutine will stay suspended, means hangs.只要没有调用
resume
或cancel
,协程就会保持挂起状态,即挂起。
when you use suspend keyword your are telling that function shoud be called inside a coroutine bode, for example:当您使用暂停关键字时,您会告诉 function 应该在协同程序中调用,例如:
suspend fun abc(){
return
}
when you want to call above function you have to call it inside coroutines such as below:当你想在 function 上面调用时,你必须在协程中调用它,如下所示:
GlobalScope.launch {
abc()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.