【问题标题】:Suspend Coroutines's execution to wait for callback挂起协程的执行等待回调
【发布时间】:2022-01-22 18:08:51
【问题描述】:

最近,我将 Coroutines 应用到我的项目中,一切似乎都很好,但今天我遇到了一个问题 [使用 Coroutine + Retrofit 将文件/图像上传到服务器][1] 使用协程+Retrofit上传文件好像没有解决办法,所以必须使用callback进行改造。

//Api interface
interface UploadFileApiKotlin {
    @Multipart
    @POST("/uploadFileApi")
    fun uploadFiles(
        @Part listUri: List<MultipartBody.Part>
    ): Call<Response<List<FileResponse>?>>
}
//ViewModel class
serviceScope.launch {
                //Insert into db
                repository.insertNewExtAct()
                //Send data into server.
                val call = RequestHelper.getUpLoadFilesKotlinRequest().uploadFiles(partList)
                call.enqueue(object : Callback<Response<List<FileResponse>?>> {
                    override fun onResponse(
                        call: Call<Response<List<FileResponse>?>>,
                        response: Response<Response<List<FileResponse>?>>
                    ) {
                        TODO("Not yet implemented")
                    }

                    override fun onFailure(
                        call: Call<Response<List<FileResponse>?>>,
                        t: Throwable
                    ) {
                        TODO("Not yet implemented")
                    }
                })
                //Wait for response from server and do logic
            }

我的问题是:如何暂停协程的执行以等待改造的回调?

谢谢兄弟。 [1]:Upload file/image into server using Coroutine + Retrofit

【问题讨论】:

    标签: android kotlin retrofit2 kotlin-coroutines coroutinescope


    【解决方案1】:

    您可以使用suspendCoroutinesuspendCancellableCoroutine 处理回调:

    serviceScope.launch {
        //Insert into db
        repository.insertNewExtAct()
        //Send data into server.
        uploadFile()
        //Wait for response from server and do logic
    }
    
    suspend fun uploadFile() = suspendCoroutine<Response<List<FileResponse>?>> { continuation ->
        val call = RequestHelper.getUpLoadFilesKotlinRequest().uploadFiles(partList)
        call.enqueue(object : Callback<Response<List<FileResponse>?>> {
            override fun onResponse(
                call: Call<Response<List<FileResponse>?>>,
                response: Response<Response<List<FileResponse>?>>
            ) {
                // Resume coroutine with a value provided by the callback
                continuation.resumeWith(response.data)
            }
    
            override fun onFailure(
                call: Call<Response<List<FileResponse>?>>,
                t: Throwable
            ) {
                continuation.resumeWithException(t)
            }
        })
    }
    

    suspendCoroutine 暂停执行它的协程,直到我们决定通过调用适当的方法 - Continuation.resume... 继续。 suspendCoroutine 主要在我们有一些带有回调的遗留代码时使用。

    还有 suspendCancellableCoroutine 构建器函数,它的行为类似于 suspendCoroutine 并具有附加功能 - 为块提供 CancellableContinuation 的实现。

    【讨论】:

    • 此解决方案有效。谢谢兄弟。
    猜你喜欢
    • 2018-09-19
    • 2019-12-19
    • 1970-01-01
    • 2016-09-23
    • 2017-06-11
    • 2021-06-10
    • 2021-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多