使用Retrofit + Coroutine时如何获取服务器返回的错误体

How to get error body returned by server when using Retrofit + Coroutine

当使用 Coroutine 和 Retrofit 来调用网络 api 时,如果服务器 returns 出现错误(响应代码!= 200),我们将得到一个异常。我的问题是如何 find/read 服务器通过 Exception 发送的错误正文(在 Json 中)?

try{
     apiService.login()
}catch(exception:Exception){
     //How to read error body from exception
     //Error body example: {"ok":false,"error":"Incorrect username or password."}
}

您只需要这样做:

(exception as? HttpException).response()?.errorBody()?.string()

这将return Json 格式的错误正文。

要处理协同程序和改造的错误,您必须创建一个密封的 class,按照以下步骤...

1:状态句柄Class

sealed class NetworkState {
  data class Success(val data : CharactersResponseModel) : NetworkState()
  object InvalidData : NetworkState()
  data class Error(val error : String) : NetworkState()
  data class NetworkException(val error : String) : NetworkState()
  sealed class HttpErrors : NetworkState() {
    data class ResourceForbidden(val exception: String) : HttpErrors()
    data class ResourceNotFound(val exception: String) : HttpErrors()
    data class InternalServerError(val exception: String) : HttpErrors()
    data class BadGateWay(val exception: String) : HttpErrors()
    data class ResourceRemoved(val exception: String) : HttpErrors()
    data class RemovedResourceFound(val exception: String) : HttpErrors()
  }
}
  1. 处理错误或成功API调用

     private suspend fun fetchCharacters() : NetworkState {
     return try {
       val response = apiService.getCharacters()
       if (response.isSuccessful) {
         if (response != null) {
           NetworkState.Success(response.body()!!)
         } else {
           NetworkState.InvalidData
         }
       } else {
         when(response.code()) {
           403 -> NetworkState.HttpErrors.ResourceForbidden(response.message())
           404 -> NetworkState.HttpErrors.ResourceNotFound(response.message())
           500 -> NetworkState.HttpErrors.InternalServerError(response.message())
           502 -> NetworkState.HttpErrors.BadGateWay(response.message())
           301 -> NetworkState.HttpErrors.ResourceRemoved(response.message())
           302 -> NetworkState.HttpErrors.RemovedResourceFound(response.message())
           else -> NetworkState.Error(response.message())
         }
       }
    
     } catch (error : IOException) {
       NetworkState.NetworkException(error.message!!)
     }
    

    }

  2. 在你的UI

    中将 liveData 或 flow to Observer 设为 neworkState