[英]Kotlin coroutine doesn't wait to be done
I have a legacy project where I want to use coroutines when contacting the backend. 我有一个遗留项目,我想在联系后端时使用协同程序。 The backend have been handle by a sdk delivered by Hybris.
后端由Hybris提供的sdk处理。 It use volley for instance, and with some callbacks.
例如,它使用齐射,并使用一些回调。 What I want is to wrap those callbacks with a coroutine.
我想要的是用协程包装那些回调。 But the problem I have is that the coroutine doesn't wait to be done, it start the coroutine, and keep going to next lines, and method returns a value, and long after that the coroutine finish.
但我遇到的问题是协程不等待完成,它启动协程,并继续前进到下一行,并且方法返回一个值,并且很久之后协程就完成了。 My code:
我的代码:
suspend fun ServiceHelper.getList(): ListOfWishes {
return suspendCancellableCoroutine { continuation ->
getAllLists(object : ResponseReceiver<ListOfWishes> {
override fun onResponse(response: Response<ListOfWishes>?) {
continuation.resume(response?.data!!)
}
override fun onError(response: Response<ErrorList>?) {
val throwable = Throwable(Util.getFirstErrorSafe(response?.data))
continuation.resumeWithException(throwable)
}
}, RequestUtils.generateUniqueRequestId(), false, null, object : OnRequestListener {
override fun beforeRequest() {}
override fun afterRequestBeforeResponse() {}
override fun afterRequest(isDataSynced: Boolean) {}
})
}
}
The helper method: 辅助方法:
suspend fun ServiceHelper.wishLists(): Deferred<ListOfWishes> {
return async(CommonPool) {
getWishList()
}
}
And where the coroutine is called: 在那里调用协程:
fun getUpdatedLists(): ListOfWishes? {
val context = Injector.getContext()
val serviceHelper = Util.getContentServiceHelper(context)
var list = ListOfWishLists()
launch(Android) {
try {
list = serviceHelper.wishLists().await()
} catch (ex: Exception){
Timber.d("Error: $ex")
}
}
return list
So instead of waiting for serviceHelper.wishLists().await()
is done, it return list. 因此,不是等待
serviceHelper.wishLists().await()
完成,而是返回列表。 I have also tried to make the method return a runBlocking{}
, but that only block the UI thread and doesn't end the coroutine. 我还试图让方法返回一个
runBlocking{}
,但这只会阻止UI线程并且不会结束协同程序。
You can do something like this: 你可以这样做:
class Presenter : CoroutineScope { // implement CoroutineScope to create local scope
private var job: Job = Job()
// local coroutine context
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
// call this when activity or fragment is destroyed to cancel the job
fun detachView() {
job.cancel()
}
fun updateLists() = wishLists().then(this) {
// update your UI here
// `it` contains the ListOfWishes
}
private fun wishLists(): Deferred<ListOfWishes> = async(Dispatchers.IO) {
getWishList()
}
private suspend fun getWishList(): ListOfWishes = suspendCancellableCoroutine { continuation ->
getAllLists(object : ResponseReceiver<ListOfWishes> {
override fun onResponse(response: Response<ListOfWishes>?) {
continuation.resume(response?.data!!)
}
override fun onError(response: Response<ErrorList>?) {
val throwable = Throwable(Util.getFirstErrorSafe(response?.data))
continuation.resumeWithException(throwable)
}
}, RequestUtils.generateUniqueRequestId(), false, null, object : OnRequestListener {
override fun beforeRequest() {}
override fun afterRequestBeforeResponse() {}
override fun afterRequest(isDataSynced: Boolean) {}
})
}
}
Extension function then
: 扩展功能
then
:
fun <T> Deferred<T>.then(scope: CoroutineScope = GlobalScope, uiFun: (T) -> Unit) {
scope.launch { uiFun(this@then.await()) }
}
To use Dispatchers.Main
add dependency to app's gradle.build
file: 要使用
Dispatchers.Main
向app的gradle.build
文件添加依赖gradle.build
:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'
Hope it will point you in the right direction. 希望它会指出你正确的方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.