简体   繁体   English

Kotlin coroutine不等待完成

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM