这篇文章有提到自定义GsonConvert来统一解析外层包裹的HttpResult关于自定义Code的统一处理,让业务只关心业务实体。
但是这个封装的还不够彻底,业务调用以及Retrofit的定义中还是透明的知道HttpResult的存在。业务调用和Retrofit的API定义应该只关心具体的业务Entity。HttpResult应该是在Gson解析的过程中自动处理,业务处不需要关心和知道它的存在。
那么问题来了,怎么给Entity包裹上HttpResult,变成HttpResult<Entity>勒。通过断点查看,发现HttpResult<Entity>的结构在GsonConvert的responseBodyConverter方法中的type 的实际类型是ParameterizedTypeImpl类型的,如下:
然后全局搜索ParameterizedTypeImpl 发现
于是拷贝retrofit2中的Utils类,简单的走读了一下源码,尽管没太看懂,然后尝试调用api,最后成功的根据Entity和HttpResult,构造出了HttpResult<Entity>的ParameterizedTypeImpl对象
//给Entity 包裹到HttpResult 的泛型里,成为HttpResult<Entity>
Utils.ParameterizedTypeImpl parameterizedType =
new Utils.ParameterizedTypeImpl(null, HttpResult.class, typeToken.getType());
拷贝Retrofit2的GsonConverterFactory与GsonRequestBodyConverter、GsonResponseBodyConverter
修改MyGsonConverterFactory的responseBodyConverter方法的传参
public final class MyGsonConverterFactory<T> 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<ResponseBody, ?> 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<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<HttpResult<T>> adapter;
GsonResponseBodyConverter(Gson gson, TypeToken<T> typeToken) {
this.gson = gson;
//给Entity 包裹到HttpResult 的泛型里,成为HttpResult<Entity>
Utils.ParameterizedTypeImpl parameterizedType =
new Utils.ParameterizedTypeImpl(null, HttpResult.class, typeToken.getType());
this.adapter =
(TypeAdapter<HttpResult<T>>) this.gson.getAdapter(TypeToken.get(parameterizedType));
}
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = this.gson.newJsonReader(value.charStream());
HttpResult<T> 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<UserEntity> login(
@Field("user") String phoneNum, @Field("pwd") String password);
}
调用,code异常在异常中判断NetApiException
loginBiz.login(userName, pw)
.compose(RxTransformers.<UserEntity>io_main())
.compose(RxTransformers.waitLoadingTransformer(loginView))
.subscribe(new Consumer<UserEntity>() {
@Override public void accept(UserEntity userEntity) throws Exception {
Log.i(TAG, "accept: userEntity=" + userEntity.getUserName());
}
}, new Consumer<Throwable>() {
@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<T> {
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;
}
}