简体   繁体   English

如何使用 Retrofit 2 处理错误响应?

[英]How to handle error response with Retrofit 2?

How to handle error response with Retrofit 2 using synchronous<\/strong> request?如何使用同步<\/strong>请求处理 Retrofit 2 的错误响应?

I need process response that in normal case return pets array and if request has bad parametrs return error json object.我需要处理响应,在正常情况下返回宠物数组,如果请求有错误的参数,则返回错误 json 对象。 How can I process this two situations?我该如何处理这两种情况?

I am trying to use this<\/a> tutorial but the main problem is mapping normal and error json to objects.我正在尝试使用本<\/a>教程,但主要问题是将正常和错误 json 映射到对象。

My normal response<\/strong> example:我的正常响应<\/strong>示例:

[ {
    "type" : "cat",
    "color": "black"
}, 
{
    "type" : "cat",
    "color": "white"
} ]

Retrofit 2 has a different concept of handling "successful" requests than Retrofit 1. In Retrofit 2, all requests that can be executed (sent to the API) and for which you're receiving a response are seen as "successful". Retrofit 2 处理“成功”请求的概念与 Retrofit 1 不同。在 Retrofit 2 中,所有可以执行(发送到 API)并且您收到响应的请求都被视为“成功”。 That means, for these requests, the onResponse callback is fired and you need to manually check whether the request is actually successful (status 200-299) or erroneous (status 400-599).这意味着,对于这些请求,onResponse 回调被触发,您需要手动检查请求是实际成功(状态 200-299)还是错误(状态 400-599)。

If the request finished successfully, we can use the response object and do whatever we wanted.如果请求成功完成,我们可以使用响应对象并做任何我们想做的事情。 In case the error actually failed (remember, status 400-599), we want to show the user appropriate information about the issue.如果错误实际上失败了(请记住,状态 400-599),我们希望向用户显示有关该问题的适当信息。

For more details refer this link有关更多详细信息,请参阅此链接

I think you should create a generic response class (let's say GenericResponse ), that is extended by a specific response class (let's say PetResponse ).我认为您应该创建一个通用响应类(假设为GenericResponse ),它由特定的响应类(假设为PetResponse )扩展。 In the first one, you include generic attributes ( error , error_description ), and in the latter, you put your specific response data ( List<Pet> ).在第一个中,您包含通用属性( errorerror_description ),在后者中,您放置了您的特定响应数据( List<Pet> )。

In your case, I would go with something like this:在你的情况下,我会用这样的东西:

class GenericResponse {
   int error;
   String error_description;
} 

class PetResponse extends GenericResponse {
   List<Pet> data;
}

So, your successful response body should look like this:因此,您成功的响应正文应如下所示:

{
   "data": [ {
        "type" : "cat",       
        "color": "black"
      }, 
      {
        "type" : "cat",
        "color": "white"
      } ]
}

And your error response body should look like this:您的错误响应正文应如下所示:

{ "error" = "-1", error_description = "Low version"}

Finally, your response object that is returned from the API call should be:最后,从 API 调用返回的响应对象应该是:

   Response<PetResponse> response;

After going through a number of solutions.在经历了许多解决方案之后。 Am posting it for more dynamic use.我发布它以供更动态的使用。 Hope this will help you guys.希望这会帮助你们。

My Error Response我的错误响应

{
"severity": 0,
"errorMessage": "Incorrect Credentials (Login ID or Passowrd)"
}

Below is as usual call method下面是通常的调用方法

private void makeLoginCall() {
    loginCall = RetrofitSingleton.getAPI().sendLogin(loginjsonObject);
    loginCall.enqueue(new Callback<Login>() {
        @Override
        public void onResponse(Call<Login> call, Response<Login> response) {
            if (response != null && response.code() == 200){
                //Success handling
            }
            else if (!response.isSuccessful()){
                mServerResponseCode = response.code();
                Util.Logd("In catch of login else " + response.message());
                /*
                * Below line send respnse to Util class which return a specific error string
                * this error string is then sent back to main activity(Class responsible for fundtionality)
                * */

                mServerMessage = Util.parseError(response) ;
                mLoginWebMutableData.postValue(null);
                loginCall = null;
            }
        }

        @Override
        public void onFailure(Call<Login> call, Throwable t) {
            Util.Logd("In catch of login " + t.getMessage());
            mLoginWebMutableData.postValue(null);
            mServerMessage = t.getMessage();
            loginCall = null;
        }
    });
}

Below Is util class to handle parsing下面是用于处理解析的 util 类

public static String parseError(Response<?> response){
    String errorMsg = null;
    try {
        JSONObject jObjError = new JSONObject(response.errorBody().string());
        errorMsg = jObjError.getString("errorMessage");
        Util.Logd(jObjError.getString("errorMessage"));
        return errorMsg ;
    } catch (Exception e) {
        Util.Logd(e.getMessage());
    }
    return errorMsg;
}

Below in viewModel observer在 viewModel 观察者下方

private void observeLogin() {
    loginViewModel.getmLoginVModelMutableData().observe(this, login -> {
        if (loginViewModel.getSerResponseCode() != null) {
            if (loginViewModel.getSerResponseCode().equals(Constants.OK)) {
                if (login != null) {
                    //Your logic here
                }
            }
           //getting parsed response message from client to handling class
            else {
                Util.stopProgress(this);
                Snackbar snackbar = Snackbar.make(view, loginViewModel.getmServerVModelMessage(), BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(android.R.string.ok, v -> { });
                snackbar.show();
            }
        } else {
            Util.stopProgress(this);
            Snackbar snackbar = Snackbar.make(view, "Some Unknown Error occured", BaseTransientBottomBar.LENGTH_INDEFINITE).setAction(android.R.string.ok, v -> { });
            snackbar.show();
        }
    });
}

Wrap all your calls in retrofit2.Response<\/code> like so:retrofit2.Response<\/code>中封装所有调用,如下所示:

@POST("user/login")
suspend fun login(@Body form: Login): Response<LoginResponse>

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

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