在Kotlin的suspendCoroutine中,AndroidNetworking永远不会返回
我正在试验新的协同程序,并试图通过一些丑陋的AndroidNetworking api请求将它们合并到现有的项目中 所以我当前的api请求正在使用这样的回调在Kotlin的suspendCoroutine中,AndroidNetworking永远不会返回,android,kotlin,coroutine,kotlinx.coroutines,Android,Kotlin,Coroutine,Kotlinx.coroutines,我正在试验新的协同程序,并试图通过一些丑陋的AndroidNetworking api请求将它们合并到现有的项目中 所以我当前的api请求正在使用这样的回调 fun getSomethingFromBackend(callback: (response: JSONArray?, error: String?) -> Unit) { AndroidNetworking.get(...).build().getAsJSONObject(object : JSONObjectRequestL
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)
}
}
现在我正试图合并这样的合作项目
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返回
我的问题是,它永远不会回来。即使我在onResponse
、onError
等中调试,它也永远不会从后端返回
但是如果我删除=suspendCoroutine
,它会工作,至少会返回,但是等待不会在corse下工作,因为执行将继续
如何解决这个问题,使await()
实际等待异步调用回调
非常感谢 试试这样的方法:
fun someFunction() {
val jsonObject: JSONObject? = runBlocking {
callGetSomething()
}
// do something with jsonObject
}
suspend fun callGetSomething(): JSONObject? = suspendCoroutine {
Something().getSomethingFromBackend { response, error ->
it.resume(response)
}
}
试着这样做:
fun someFunction() {
val jsonObject: JSONObject? = runBlocking {
callGetSomething()
}
// do something with jsonObject
}
suspend fun callGetSomething(): JSONObject? = suspendCoroutine {
Something().getSomethingFromBackend { response, error ->
it.resume(response)
}
}
您的主要问题是您试图使用
runBlocking
,这取消了您为项目引入异步网络库和协同路由所做的所有工作。如果您在等待结果时确实想要阻塞,那么只需使用阻塞网络调用即可
如果要继续使用异步网络操作,请忘记阻塞someFunction
,直接从launch
块使用callGetSomething
:
override fun onSomeEvent(...) {
this.launch {
val result = callGetSomething(...)
// use the result, you're on the GUI thread here
}
}
以上假设您的
此
是一个活动
、片段
、视图模型
或实现协同场景
的类似对象。查看它以了解如何实现这一点。您的主要问题是,您试图使用运行阻塞
,这取消了您为在项目中引入异步网络库和协同路由所做的所有工作。如果您在等待结果时确实想要阻塞,那么只需使用阻塞网络调用即可
如果要继续使用异步网络操作,请忘记阻塞someFunction
,直接从launch
块使用callGetSomething
:
override fun onSomeEvent(...) {
this.launch {
val result = callGetSomething(...)
// use the result, you're on the GUI thread here
}
}
以上假设您的
此
是一个活动
、片段
、视图模型
或实现协同场景
的类似对象。看看它,看看如何做到这一点。好的,谢谢大家的帮助。
我将解释我是如何发现这个问题的,以及我是如何解决它的
在详细研究了回调和协同路由之后,我决定在回调期间记录线程名称,如下所示Log.d(“标记”,“执行线程:”+thread.currentThread().name)
这使我认识到,所有回调(错误和成功)实际上都在主线程上运行,而不是在我为其设置的协程上运行
因此,我的协同程序中的代码在D/TAG:Execution-thread:DefaultDispatcher-worker-1
中运行,但回调在D/TAG:Execution-thread:main
上运行
解决方案
runBlocking
:这将阻塞主线程,在这种情况下,这就是回调永远不会返回的原因Dispatchers.Main
,这样我就可以在UI中实际使用返回的值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)
}
}
好的,谢谢大家的帮助。 我将解释我是如何发现这个问题的,以及我是如何解决它的 在详细研究了回调和协同路由之后,我决定在回调期间记录线程名称,如下所示
Log.d(“标记”,“执行线程:”+thread.currentThread().name)
这使我认识到,所有回调(错误和成功)实际上都在主线程上运行,而不是在我为其设置的协程上运行
因此,我的协同程序中的代码在D/TAG:Execution-thread:DefaultDispatcher-worker-1
中运行,但回调在D/TAG:Execution-thread:main
上运行
解决方案
runBlocking
:这将阻塞主线程,在这种情况下,这就是回调永远不会返回的原因Dispatchers.Main
,这样我就可以在UI中实际使用返回的值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)
}
}
谢谢@Sergey,但它不起作用,
AndroidNetworking.get正在调用,协同程序正在等待,但回调从未被调用。没有响应,没有错误,什么都没有…谢谢@Sergey,但它不工作,AndroidNetworking.get正在调用,协同程序正在等待,但从未调用回调。没有响应,没有错误,什么都没有…你确定总是调用getSomethingFromBackend
回调吗?另外,如果someFunction
和回调应该从同一个线程调用,那么它就不会发生,因为你用runBlocking
阻止了它,你确定总是调用getSomethingFromBackend
回调吗?另外,如果someFunction
和回调应该从同一个线程调用,那么它就不会发生,因为你用runBlocking
阻止了它