简体   繁体   English

kotlin+retrofit+coroutine+mvvm中如何处理服务端api返回的错误响应

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

I have two different response from the same endpoint.我从同一个端点有两个不同的响应。 One being the actual success result data model and one being an error response model.一种是实际成功结果数据模型,一种是错误响应模型。 Both json structure like this:两个json结构都是这样的:

SuccessResponse:成功响应:

{
   "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."
   }
}

ErrorResponse:错误响应:

{
    "message": "Login Failed"
}

I can handle the success response but I can't show the error message what I get from the server.我可以处理成功响应,但无法显示从服务器获得的错误消息。 I have tried many ways but I can't do this.我尝试了很多方法,但我做不到。 Here my I share my some aspect what I did在这里我分享我的一些方面我做了什么

MainViewModel.kt主视图模型.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())
    }

I need a solution while server give me error message I want to show same error message on my front side.我需要一个解决方案,而服务器给我错误消息我想在我的正面显示相同的错误消息。 How can I achieve this?我怎样才能做到这一点?

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");
}

The body of the response (be it success or failure) is response.body().响应的主体(成功或失败)是 response.body()。 And if you want to get it as a String, then call response.body().string().如果你想把它作为一个字符串来获取,那么调用 response.body().string()。 Since you want to read message object from the response you need to convert it into Json.由于您想从响应中读取消息对象,因此需要将其转换为 Json。

If you are a following MVVM pattern then I suggest to create a sealed class for the API calls.如果您遵循 MVVM 模式,那么我建议为 API 调用创建一个密封类。

To handle api success and failure or network issue.处理 api 成功和失败或网络问题。 Resource class is going to be generic because it will handle all kind of api response资源类将是通用的,因为它将处理所有类型的 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>()

}

on the base repository while calling the API, you can return the resource whether it is success or failure.在调用 API 时在基础存储库上,无论成功还是失败,您都可以返回资源。

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)
                    }
                }
            }
        }
    }
}

If you follow this pattern you'll be able to handle all the failure and success response, I hope this will help.如果您遵循此模式,您将能够处理所有失败和成功响应,我希望这会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM