我有一个遗留项目,我想在联系后端时使用协程。后端由Hybris提供sdk处理。例如,它使用volley,并带有一些回调。我想要的是用协程包装这些回调函数。但我遇到的问题是,协程不会等待完成,它会启动协程,然后一直转到下一行,方法返回一个值,然后很长一段时间协程结束。我的代码:
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) {}
})
}
}帮助器方法:
suspend fun ServiceHelper.wishLists(): Deferred<ListOfWishes> {
return async(CommonPool) {
getWishList()
}
}其中的协程被称为:
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因此,它不是等待列表完成,而是返回serviceHelper.wishLists().await()。我还试图让该方法返回一个runBlocking{},但这只会阻塞UI线程,而不会结束协程。
发布于 2022-02-05 20:05:30
协程不是这样工作的。如果getUpdatedLists()方法本身不是suspend方法,那么它不能等待协程来完成其执行。如果在Activity或Fragment中定义了方法getUpdatedLists(),那么在执行serviceHelper.wishLists().await()之后,您可以启动一个协程并在其中执行一些操作,例如更新UI。它看起来像这样:
fun loadUpdatedLists() {
val context = Injector.getContext()
val serviceHelper = Util.getContentServiceHelper(context)
lifecycleScope.launch {
try {
val list = serviceHelper.wishLists().await()
// use list object, for example Update UI
} catch (ex: Exception){
Timber.d("Error: $ex")
}
}
}lifecycleScope - CoroutineScope绑定到LifecycleOwner的Lifecycle。要使用它添加依赖项:
androidx.lifecycle:lifecycle-runtime-ktx:2.4.0 or higher.发布于 2018-12-12 17:00:52
你可以这样做:
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) {}
})
}
}扩展函数then
fun <T> Deferred<T>.then(scope: CoroutineScope = GlobalScope, uiFun: (T) -> Unit) {
scope.launch { uiFun(this@then.await()) }
}要使用Dispatchers.Main将依赖项添加到应用程序的gradle.build文件:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'希望它能为你指明正确的方向。
https://stackoverflow.com/questions/45833042
复制相似问题