使用Retrofit进行自定义错误处理

时间:2014-09-25 16:30:19

标签: android retrofit

我正在使用的REST Api具有根据状态从服务器发送的自定义代码和消息,我想实现仅调用Callback<T>方法的自定义success如果状态代码为0。

示例SUCCESS从服务器收到的响应:

{
  "code":"0",
  "message":"success",
  "data": {
    "actual_data":"goes_here",
    "need_to_construct_objects","from_data"
  }
}

失败响应示例:

{
  "code":"301",
  "message":"wrong_password",
  "data": {
    "actual_data":"will_be_null",
    "no_need_to_construct_objects","from_data"
  }
}
所有请求都会返回

codemessagedata包含实际响应值,因此我想执行以下操作:

  1. 检查代码消息,如果代码为0,则仅调用success()
  2. 如果请求失败或代码!= 0
  3. ,请致电failure()
  4. 根据数据响应构建自定义对象,并通过success()
  5. 传递它们

    最好的方法是什么?我到处搜索,找不到一个好的解决方案。我得到的唯一一个是让所有自定义对象都有codemessage字段,并检查success()内的值,但如果有人忘记检查,这可能会导致问题在继续之前code

5 个答案:

答案 0 :(得分:3)

只需创建一个实现Callback的抽象类,然后声明自己的抽象成功和失败方法,就可以快速完成。抽象类将处理Retrofit的标准回调方法,解释响应并相应地调用抽象方法。

我认为另一种可能的方法是覆盖Retrofit的Client接口来构建自己的Response对象。

如果您延长OkClient,可以这样:

public class CustomClient extends OkClient {

    @Override public Response execute(Request request) throws IOException {
          Response originalRespone = super.execute(request);

          int statusCode = 0;
          //TODO: read JSON response here (using GSON or similar, and extract status code and message... etc.)

          //Convert the status code to HTTP standard status codes, according to the documentation you have.
          if(statusCode == 0) statusCode = 200;
          //Reconstruct a Response object
          return new Response(originalResponse.getUrl(), statusCode, originalResponse.getReason() /*should probably replace with parsed message*/, originalResponse.getHeaders(), originalResponse.getBody());
    }

这可能比在Callback中处理你的情况要多得多,但我认为如果API在某些时候转换为RESTful API约定会有所帮助。

此解决方案虽然有自己的问题,因为这意味着JSON转换将运行两次。一个在你的客户端,另一个在Retrofit。目前还不确定正确的方法。可能是TypedInput和一个传递已转换对象的虚​​拟转换器。

答案 1 :(得分:1)

创建一个自定义的ResponseBodyConverter,如下所示:

public class CustomResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final TypeAdapter<T> adapter;

CustomResponseBodyConverter(TypeAdapter<T> adapter) {
    this.adapter = adapter;
}

@Override
public T convert(ResponseBody value) throws IOException,CustomException {
    String json = "";
    try {
        String body = value.string();
        json = new JSONObject(body).getJSONObject("data").toString();
        int code = new JSONObject(body).getInt("code");
        String message = new JSONObject(body).getString("message");
        if(code != 0){
            throw new CustomException(message);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
    return adapter.fromJson(json);
   }
}

答案 2 :(得分:0)

这至少可以让你开始。您基本上可以创建自己的自定义回调,然后处理成功。看看发送了什么并做你需要的。

  public class CustomCallback implements Callback {
    @Override
        public void success(Object o, Response response) {

                //Check for success
                //if( Success )
                //callback.success(o, response);
                //else
                //Check for error
                //callback.failure(error);


        }
    }

答案 3 :(得分:0)

在您的情况下,您可以拥有一个映射您的json响应的类:

class CustomResponse {
  String code;
  String message;
  Data data;

  static class Data {
    String actualData;
    String needToContructObjects;
    String noNeedToContructObjects;
  }
}

然后,由于您回到java对象世界,您可以在success方法回调中包含一个类似工厂的对象,该对象根据返回的自定义响应创建所需的对象。如果您想在故障回调中获得此响应,我会重新考虑使用Retrofit,因为您的API没有遵循良好的Rest设计。

虽然这很有可能,并且了解您可能不参与API开发,但请注意,这不是一个好的API设计方法。如果要向服务器发送登录请求,则可以将此请求理解为创建资源的请求(例如,经过身份验证的用户会话)。如果您没有发送正确的参数(在这种特定情况下使用正确的用户名和密码),服务器应该拒绝资源创建请求并发送回400个(4xx)http状态代码,表明您的请求是不知道怎么回事。 Retrofit会理解这个4xx状态代码并调用你的故障回调,你可以在那里适当地处理响应。

答案 4 :(得分:0)

实现自定义回调是一个更好的主意。你可以在下面举例说明。

public abstract class DefaultRequestCallback<T> implements Callback<T> {

    public abstract void failure(Meta meta);

    public abstract void success(T responseBean);

    @Override
    public void success(T baseResponseBean, Response response) {
        // You can check your responsebean's error code and 
        // convert it to a default error
        BaseResponseBean bean = (BaseResponseBean) baseResponseBean;
        if (bean == null) {
            failure(new Meta(ApplicationConstants.ERROR_RETROFIT, "Unknown Error!"));
        } else if (bean.getMeta() != null && bean.getMeta().getCode() != ApplicationConstants.RESULT_SUCCESS) {
            failure(bean.getMeta());
        } else {
            success(baseResponseBean);
        }
    }

    @Override
    public void failure(RetrofitError error) {
        // Convert default error to your custom error.
        Meta meta = new Meta(ApplicationConstants.ERROR_RETROFIT, "Error Unknwon");
        failure(meta);
    }
}

将自定义回调提供给改装服务界面方法。

void yourMethod(DefaultRequestCallback<YourResponseBean> callback);

祝你好运。