Retrofit响应数据及异常处理策略
这篇文章有提到自定义GsonConvert来统一解析外层包裹的HttpResult关于自定义Code的统一处理,让业务只关心业务实体。
但是这个封装的还不够彻底,业务调用以及Retrofit的定义中还是透明的知道HttpResult的存在。业务调用和Retrofit的API定义应该只关心具体的业务Entity。HttpResult应该是在Gson解析的过程中自动处理,业务处不需要关心和知道它的存在。
那么问题来了,怎么给Entity包裹上HttpResult,变成HttpResult
然后全局搜索ParameterizedTypeImpl 发现
于是拷贝retrofit2中的Utils类,简单的走读了一下源码,尽管没太看懂,然后尝试调用api,最后成功的根据Entity和HttpResult,构造出了HttpResult
//给Entity 包裹到HttpResult 的泛型里,成为HttpResult
Utils.ParameterizedTypeImpl parameterizedType =
new Utils.ParameterizedTypeImpl(null, HttpResult.class, typeToken.getType());
拷贝Retrofit2的GsonConverterFactory与GsonRequestBodyConverter、GsonResponseBodyConverter
修改MyGsonConverterFactory的responseBodyConverter方法的传参
public final class MyGsonConverterFactory extends Factory {
private final Gson gson;
public static MyGsonConverterFactory create() {
return create(new Gson());
}
public static MyGsonConverterFactory create(Gson gson) {
if(gson == null) {
throw new NullPointerException("gson == null");
} else {
return new MyGsonConverterFactory(gson);
}
}
private MyGsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return new GsonResponseBodyConverter(this.gson,TypeToken.get(type));
}
@Override
public Converter, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter> adapter = this.gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter(this.gson, adapter);
}
}
修改GsonResponseBodyConverter的构造入参,和泛型定义
final class GsonResponseBodyConverter implements Converter {
private final Gson gson;
private final TypeAdapter> adapter;
GsonResponseBodyConverter(Gson gson, TypeToken typeToken) {
this.gson = gson;
//给Entity 包裹到HttpResult 的泛型里,成为HttpResult
Utils.ParameterizedTypeImpl parameterizedType =
new Utils.ParameterizedTypeImpl(null, HttpResult.class, typeToken.getType());
this.adapter =
(TypeAdapter>) this.gson.getAdapter(TypeToken.get(parameterizedType));
}
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = this.gson.newJsonReader(value.charStream());
HttpResult result;
try {
result = this.adapter.read(jsonReader);
//code!=1,服务器校验返回的错误信息
if (result != null&&result.getCode()!=1){
throw new NetApiException(result.getCode(),result.getMsg());
}
} finally {
value.close();
}
//返回实际的Entity
return result == null ? null : result.getData();
}
}
这样在定义的时候和使用的时候都只知道业务的Entity,而不知道HttpResult的存在。
如:
API定义
public interface LoginApi {
@FormUrlEncoded @POST("lawyer/login") Flowable login(
@Field("user") String phoneNum, @Field("pwd") String password);
}
调用,code异常在异常中判断NetApiException
loginBiz.login(userName, pw)
.compose(RxTransformers.io_main())
.compose(RxTransformers.waitLoadingTransformer(loginView))
.subscribe(new Consumer() {
@Override public void accept(UserEntity userEntity) throws Exception {
Log.i(TAG, "accept: userEntity=" + userEntity.getUserName());
}
}, new Consumer() {
@Override public void accept(Throwable throwable) throws Exception {
if (throwable instanceof NetApiException) {
Log.i(TAG, "accept:登录信息错误 " + throwable.getMessage());
} else {
Log.i(TAG, "accept: " + throwable.getMessage());
}
}
});
附上相关类的定义
public class HttpResult {
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
}
public class NetApiException extends RuntimeException{
private int code;
private String msg;
public NetApiException(int code, String msg) {
this.code = code;
this.msg = msg;
}
@Override public String toString() {
return "Code="+code+" Msg="+msg;
}
}