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

How to handle 204 response in Retrofit using Kotlin Coroutines?

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

我有这样定义的 Retrofit 服务:

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

此调用 returns HTTP 204 无内容 响应,导致 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.onResponse(KotlinExtensions.kt:43)
        at retrofit2.OkHttpCall.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 响应而不崩溃?

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

retrofit no content issue

您可以使用 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!
    }

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

  1. 在你的API界面中,像这样调用你的API,

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

其中,响应是 retrofit2.Response

  1. 从调用 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))
     }
    

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

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