如何在 kotlin+retrofit+coroutine+mvvm 中处理来自服务器 api 的错误响应 return

How to handle error response return from server api in kotlin+retrofit+coroutine+mvvm

我有两个来自同一端点的不同响应。一种是实际成功结果数据模型,一种是错误响应模型。两者 json 结构如下:

成功响应:

{
   "result":{
      "id":1,
      "name_en":"Stack Over Flow",
      "summary":"Stack Overflow is the largest, most trusted online community for developers to learn, share​ ​their programming ​knowledge, and build their careers."
   }
}

错误响应:

{
    "message": "Login Failed"
}

我可以处理成功响应,但无法显示从服务器获得的错误消息。我尝试了很多方法,但我做不到。 在这里我分享我的一些方面我做了什么

MainViewModel.kt

var job: Job? = null
val myDataResponse: MutableLiveData<HandleResource<DataResponse>> =MutableLiveData()

fun myData() {
        job = CoroutineScope(Dispatchers.IO).launch {

            val myDataList = mainRepository.myData()

            withContext(Dispatchers.Main) {
                myDataResponse.postValue(handleMyDataResponse(myDataList))
            }

        }

    }
private fun handleMyDataResponse(myDataResponse: Response<DataResponse>): HandleResource<DataResponse>? {
        if (myDataResponse.isSuccessful) {

            myDataResponse.body()?.let { myDataData ->
                return HandleResource.Success(myDataData)
            }

        }

        return HandleResource.Error(myDataResponse.message())
    }

当服务器给我错误消息时我需要一个解决方案我想在我的正面显示相同的错误消息。我怎样才能做到这一点?

private fun handleMyDataResponse(myDataResponse: Response<DataResponse>): HandleResource<DataResponse>? {
      
      myDataResponse.body()?.let { myDataData ->    
         if (myDataResponse.code() == 200) {                     
           return HandleResource.Success(myDataData )                 
         } else {
           val rawResponse = myDataData.string()                        
           return HandleResource.Error(getErrorMessage(rawResponse))     
         } 
      }
    }


fun getErrorMessage(raw: String): String{   
  val object = JSONObject(raw);
  return object.getString("message");
}

响应的正文(成功或失败)是 response.body()。如果你想把它作为一个字符串来获取,那么调用 response.body().string()。由于您想从响应中读取消息对象,因此需要将其转换为 Json.

如果您遵循 MVVM 模式,那么我建议为 API 调用创建一个密封的 class。

处理api 成功和失败或网络问题。 Resource class 将是通用的,因为它将处理所有类型的 api 响应

sealed class Resource<out T> {

    data class Success<out T>(val value: T): Resource<T>()

    data class Failure(
        val isNetworkErro: Boolean?,
        val errorCode: Int?,
        val errorBody: ResponseBody?
    ): Resource<Nothing>()

}

在基础资源库上调用API时,您可以return资源,无论是成功还是失败。

abstract class BaseRepository {
    suspend fun  <T> safeApiCall(
        apiCall: suspend () -> T
    ): Resource<T>{
        return withContext(Dispatchers.IO){
            try {
                Resource.Success(apiCall.invoke())
            } catch (throwable: Throwable){
                when (throwable){
                    is HttpException -> {
                        Resource.Failure(false,throwable.code(), throwable.response()?.errorBody())
                    }
                    else ->{
                        Resource.Failure(true, null, null)
                    }
                }
            }
        }
    }
}

如果您遵循此模式,您将能够处理所有失败和成功响应,希望这会有所帮助。