Retrofit2+Rxjava2 自定义GsonConvert 将Http返回Code状态统一处理

Retrofit响应数据及异常处理策略

这篇文章有提到自定义GsonConvert来统一解析外层包裹的HttpResult关于自定义Code的统一处理,让业务只关心业务实体。

但是这个封装的还不够彻底,业务调用以及Retrofit的定义中还是透明的知道HttpResult的存在。业务调用和Retrofit的API定义应该只关心具体的业务Entity。HttpResult应该是在Gson解析的过程中自动处理,业务处不需要关心和知道它的存在。

那么问题来了,怎么给Entity包裹上HttpResult,变成HttpResult勒。通过断点查看,发现HttpResult的结构在GsonConvert的responseBodyConverter方法中的type 的实际类型是ParameterizedTypeImpl类型的,如下:

Retrofit2+Rxjava2 自定义GsonConvert 将Http返回Code状态统一处理_第1张图片
image.png

然后全局搜索ParameterizedTypeImpl 发现

Retrofit2+Rxjava2 自定义GsonConvert 将Http返回Code状态统一处理_第2张图片
image.png

于是拷贝retrofit2中的Utils类,简单的走读了一下源码,尽管没太看懂,然后尝试调用api,最后成功的根据Entity和HttpResult,构造出了HttpResult的ParameterizedTypeImpl对象

    //给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 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;
  }
}

你可能感兴趣的:(Retrofit2+Rxjava2 自定义GsonConvert 将Http返回Code状态统一处理)