最近跟朋友在一起吃饭,发现现在很多人都已经在用retrofit 来做为网络请求框架!谈到其中一个问题就是跟后台的沟通问题,我以前的项目后台返回给我的数据都是按照这样返回给我的: 如果正常返回result 对应的是一个jsonArray, 如果返回的错误信息,result 对应的就是一个空的数组,而不是返回给我的json对象!,这样来说,retrofit 解析是完全没有问题的,也就是说你的bean 的结构是什么样,就必须要后台按照那个结构给你 -----------
后来新项目,后台新架构,对,问题出现了,对的 ,就是大家看到的这个错误
begin array but was object
而且后台直接拒绝以前后台的做法,原因是他们有一个拦截器,错误信息直接给你拦截掉了,哈哈,尴尬了,拦截器是统一的,改的成本太大,so ,自己想办法吧 ,也是百度,google了一番,最后也是找到了这样一种解决方案:再retrofit拿到response 之后,拦截判断一下.如果是正常的response code 就直接放行,如果不是,就直接抛出一个自定义的异常类,这个异常类包含errorCode,和errorMsg ,对的,这些已经够我们用了!下面上代码,为了让其他人少走弯路就直接把代码贴上了,直接拿走,不要客气!
首先上正常用retrofit创建
这个我就上图片了,因为你们也用不到,我们就是从GsonConverterFactory入手,需要自定义一个转换器
CustomGsonConverterFactory
public final class CustomGsonConverterFactory extends Converter.Factory {
public static CustomGsonConverterFactory create() {
return create(new Gson());
}
public static CustomGsonConverterFactory create(Gson gson) {
return new CustomGsonConverterFactory(gson);
}
private final Gson gson;
private CustomGsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
//返回一个自定义的ResponseConverter 重点都在这里面
return new CustomResponseConverter<>(gson, adapter,type);
}
@Override
public Converter, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter adapter = this.gson.getAdapter(TypeToken.get(type));
//返回一个自定义的RequestBodyConverte 这个就直接把retrofit 的GsonConverterFactory 里面的RequestBodyConverte 复制过来到自己的定义的类就行了
return new GsonRequestBodyConverter(this.gson, adapter);
}
}
从上面注释大家也就知道了,重点是CustomResponseConverter ,因为所有的处理逻辑都在里面,下面贴这个类的代码,有兴趣的可以看下源码,对比下自定义和源码的区别
CustomResponseConverterimplements
final class CustomResponseConverter implements Converter {
private final Gson gson;
private TypeAdapter adapter;
private Type mType;
CustomResponseConverter(Gson gson, TypeAdapter mAdapter, Type mType) {
this.gson = gson;
this.adapter = mAdapter;
this.mType = mType;
}
@Override
public T convert(ResponseBody value) throws IOException {
ErrorResponse errorResponse = new ErrorResponse();
try {
String body = value.string();
JSONObject json = new JSONObject(body);
String code = json.getString("respCode");
String msg = json.getString("respMsg");
if (Constant.RESPCODE.equals(code)) {
//此处的RESPCODE为你和后台约定返回的正常的responseCode
return gson.fromJson(body, mType);
} else {
errorResponse = gson.fromJson(body, ErrorResponse.class);
//ErrorResponse 为自定义的错误类
//抛一个自定义ResultException 传入失败时候的状态码,和信息
throw new ResultException(errorResponse.getRespCode(), errorResponse.getRespMsg());
}
} catch (Exception e) {
throw new ResultException(errorResponse.getRespCode(), errorResponse.getRespMsg());
} finally {
value.close();
}
}
}
自定义的CustomGsonConverterFactory所需要的元素都已经到位了,下面就是替换掉原生的GsonConverterFactory
OK小伙伴们,就是这么简单,为了小伙伴更轻松的解决问题,我把所需要的类,都贴在下面,是不是懂你呢
ErrorResponse
public class ErrorResponse {
public ErrorResponse(){
this.respCode= "";
this.respMsg="";
}
/**
*
*/
private String respCode;
/**
*
*/
private String respMsg;
public String getRespCode() {
return respCode;
}
public void setRespCode(String respCode) {
this.respCode = respCode;
}
public String getRespMsg() {
return respMsg;
}
public void setRespMsg(String respMsg) {
this.respMsg = respMsg;
}
@Override
public String toString() {
return "ErrorResponse{" +
"respCode='" + respCode + '\'' +
", respMsg='" + respMsg + '\'' +
'}';
}
}
自定义的 ResultExceptionextends
public class ResultExceptionextends RuntimeException {
private StringrespMsg;
private StringrespCode;
public ResultException(String respCode, String respMsg) {
this.respMsg = respMsg;
this.respCode = respCode;
}
public StringgetRespMsg() {
return respMsg;
}
public void setRespMsg(String respMsg) {
this.respMsg = respMsg;
}
public StringgetRespCode() {
return respCode;
}
public void setRespCode(String respCode) {
this.respCode = respCode;
}
}
OK 到此结束!