我正在使用的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"
}
}
所有请求都会返回 code
和message
,data
包含实际响应值,因此我想执行以下操作:
success()
。failure()
success()
最好的方法是什么?我到处搜索,找不到一个好的解决方案。我得到的唯一一个是让所有自定义对象都有code
和message
字段,并检查success()
内的值,但如果有人忘记检查,这可能会导致问题在继续之前code
。
答案 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);
祝你好运。