如何使用 Kotlin Coroutines 在 Retrofit 中处理 204 响应?

Posted

技术标签:

【中文标题】如何使用 Kotlin Coroutines 在 Retrofit 中处理 204 响应?【英文标题】:How to handle 204 response in Retrofit using Kotlin Coroutines? 【发布时间】:2020-04-25 10:05:25 【问题描述】:

我正在使用带有 Kotlin 协程的 Retrofit 2.7.1。

我有这样定义的改造服务:

@PUT("/users/userId.json")
suspend fun updateUserProfile(
        @Path("userId") userId: String,
        @Query("display_name") displayName: String) : Void

此调用返回 HTTP 204 No Content 响应,这会导致 Retrofit 崩溃:

kotlin.KotlinNullPointerException: Response from com.philsoft.test.api.UserApiService.updateUserProfile was null but response body type was declared as non-null
        at retrofit2.KotlinExtensions$await$2$2.onResponse(KotlinExtensions.kt:43)
        at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:129)
        at okhttp3.RealCall$AsyncCall.execute(RealCall.java:174)
        at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)

如何在改造中使用协程处理 204 响应而不崩溃?

【问题讨论】:

可能在这里回答:***.com/questions/37116364/… 【参考方案1】:

据此,在改造方法声明中使用Response<Unit>

retrofit no content issue

【讨论】:

我在这个问题上花了将近 2 天的时间,终于可以正常使用您的解决方案了。谢谢。【参考方案2】:

您可以使用Response<Unit> 来处理使用Retrofit 的204 个响应,但是当您这样处理时,Retrofit 不会针对4xx 响应或其他异常情况抛出异常。

您可以使用以下代码处理这些情况:

return try 
        val result = apiCall.invoke()
        return if (result is Response<*>) 
            if (result.code() >= 400) 
                // create an error from error body and return
             else 
                // return success result
            
         else 
            // directly return success result
        
     catch (t: Throwable) 
        // create an error from throwable and return it!
    

【讨论】:

如何从205获取消息数据?【参考方案3】:

用示例代码解释@Dmitri 的答案:

    在您的 APIInterface 中,像这样调用您的 API,

     @GET(AppConstants.APIEndPoints.GET_NEWS)
     suspend fun getNews(
         @Query("limit") limit: String,
     ): Response<NewsListResponseModel>
    

其中,响应是retrofit2.Response

    从您调用 API 的位置,检查来自函数的状态代码,例如 apiResponse.code()

    val apiResponse = apiEndPointsInterface.getNews(limit)
    if (apiResponse.code() == HttpURLConnection.HTTP_OK) 
         //response success
         ResultOf.Success(apiResponse.body()!!))
      else 
         //handle your other response codes here
         ResultOf.Failure("No Data Found.", null))
     
    

【讨论】:

最后它可以与您的解决方案一起正常工作。谢谢。【参考方案4】:

这可能对某人有帮助 我添加了错误的标头,导致我出现 HTTP 400 Bad request 错误。

      .addHeader("Content-Encoding", "UTF-8")
      .header("Accept-Encoding", "identity")     

【讨论】:

这是我遇到的一个案例,当时我添加了错误的标题,所以可能会帮助某人交叉检查。 @RichardBarber:甚至在编辑之前,它就提供了答案。 @JeremyCaney 回滚完成

以上是关于如何使用 Kotlin Coroutines 在 Retrofit 中处理 204 响应?的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin Coroutines:等待多个线程完成

Spring WebFlux Reactive 和 Kotlin Coroutines 启动错误

有没有办法在 Kotlin 中使用 coroutines/Flow/Channels 实现这个 rx 流?

Kotlin Coroutines 选择 Dispatcher

Kotlin Coroutines 中是不是有 RxJava 主题的类似物?

使用 Kotlin Coroutines 更新我的 TextView 会导致它崩溃: