首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Kotlin协程不会等待完成

Kotlin协程不会等待完成
EN

Stack Overflow用户
提问于 2017-08-23 15:16:28
回答 2查看 1.9K关注 0票数 3

我有一个遗留项目,我想在联系后端时使用协程。后端由Hybris提供sdk处理。例如,它使用volley,并带有一些回调。我想要的是用协程包装这些回调函数。但我遇到的问题是,协程不会等待完成,它会启动协程,然后一直转到下一行,方法返回一个值,然后很长一段时间协程结束。我的代码:

代码语言:javascript
复制
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) {}
        })
    }
}

帮助器方法:

代码语言:javascript
复制
suspend fun ServiceHelper.wishLists(): Deferred<ListOfWishes> {
    return async(CommonPool) {
        getWishList()
    }
}

其中的协程被称为:

代码语言:javascript
复制
    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线程,而不会结束协程。

EN

回答 2

Stack Overflow用户

发布于 2022-02-05 20:05:30

协程不是这样工作的。如果getUpdatedLists()方法本身不是suspend方法,那么它不能等待协程来完成其执行。如果在ActivityFragment中定义了方法getUpdatedLists(),那么在执行serviceHelper.wishLists().await()之后,您可以启动一个协程并在其中执行一些操作,例如更新UI。它看起来像这样:

代码语言:javascript
复制
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绑定到LifecycleOwnerLifecycle。要使用它添加依赖项:

代码语言:javascript
复制
androidx.lifecycle:lifecycle-runtime-ktx:2.4.0 or higher.
票数 0
EN

Stack Overflow用户

发布于 2018-12-12 17:00:52

你可以这样做:

代码语言:javascript
复制
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

代码语言:javascript
复制
fun <T> Deferred<T>.then(scope: CoroutineScope = GlobalScope, uiFun: (T) -> Unit) {
    scope.launch { uiFun(this@then.await()) }
}

要使用Dispatchers.Main将依赖项添加到应用程序的gradle.build文件:

代码语言:javascript
复制
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1'

希望它能为你指明正确的方向。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45833042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档