使用Retrofit 的特性#addConverterFactory(..),将服务器的数据做统一的处理

Q: 当我们的服务器的json数据形如下面:

{
    code:0,//这里的数字代表了服务器返回的不同状况,通常只有1才是正确的
    msg:"提示信息",//这里代表了返回数据的提示信息
    data:<obj>|<array>  //这里真正需要的数据
}

可是很多时候,我们队数据的处理是一样的,只有code==1的时候才能需要解析data的数据,其他时候我们直接抛异常处理.
那么我们怎么封装统一处理数据呢?
有两种方法:
1.使用Rxjava 的特性,在返回数据前,统一对数据进行解析处理;
2.使用Retrofit 的特性,在创建Retrofit,有一个方法Retrofit.Build#addConverterFactory(Converter.Factory factory),可以对服务器的数据进行解析.通常我们这样写:

new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create())

进行我们自定义一个自己的ConverterFactory


例如

定义一个接口

public class ApiResponse<T> {
    int code;
    String message;
    T data;

    public boolean isSuccess(){
        return code == 1;
    }
}


public interface HouseApi {

    @POST("v1/user/login")
    @FormUrlEncoded
    Observable<ApiResponse> login();
                                        }
使用Rxjava 的特性解决
//1.先得到Retrofit
Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(Constants.URLS.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build().create(HouseApi.class).login(loginCode, md5Password);

//2.然后使用map方法统一对数据进行出
                .map(ApiResponseMapper.create())

//
public class ApiResponseMapper {

    public static final String TAG = ApiResponseMapper.class.getSimpleName();

    public static <T> Function<ApiResponse<T>, T> create() {
        return apiResponse -> {
            if (apiResponse.isSuccess()) {//就是判断code==1
                return apiResponse.getData();
            } else {//不然就会跑异常
                throw new ApiException(apiResponse.getMsg());
            }
        };
    }
}

//可是这样会出现一个问题,集合每个网络请求都调用:

Observable#map(ApiResponseMapper.create())

其实也是一个麻烦,没意义.


Q:有没有一个方法,完全根据我们自己服务器的数据的特性解决这个问题呢?
A:使用Retrofit 的特性:addConverterFactory(GsonConverterFactory.create())

GsonConverterFactory 其实就是一个对服务器的数据解析gson解析的方法, 我们可以对解析后的数据在进行判断code是否为1的处理,不符合就跑异常,岂不是非常好?

public class QxydGsonConverterFactory extends Converter.Factory{
..
}

改方法继承Converter.Factory ,复写responseBodyConverter和requestBodyConverter方法即可

  • 前者是对response 的数据gson解析后判断code和类型;
  • 后者是对requese sh
public class DsGsonConverterFactory extends Converter.Factory {

    public static final String TAG = DsGsonConverterFactory.class.getSimpleName();
    private final Gson gson;

    private DsGsonConverterFactory(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        this.gson = gson;
    }

    public static DsGsonConverterFactory create() {
        return create(new Gson());
    }

    public static DsGsonConverterFactory create(Gson gson) {
        return new DsGsonConverterFactory(gson);
    }


    @Nullable
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonResponseBodyConverter<>(gson, adapter);
    }

    @Nullable
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new GsonRequestBodyConverter(gson, adapter);
    }

    private final static class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {

        private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
        private static final Charset UTF_8 = Charset.forName("UTF-8");

        private final Gson gson;
        private final TypeAdapter<T> adapter;

        GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }

        @Override public RequestBody convert(T value) throws IOException {
            Buffer buffer = new Buffer();
            Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);

            JsonWriter jsonWriter = gson.newJsonWriter(writer);
            adapter.write(jsonWriter, value);
            jsonWriter.close();
            return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
        }
    }

    private final static class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
        private final Gson gson;
        private final TypeAdapter<T> adapter;

        GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
            this.gson = gson;
            this.adapter = adapter;
        }

        @Override public T convert(ResponseBody value) throws IOException {
            JsonReader jsonReader = gson.newJsonReader(value.charStream());
            try {
                T entity = adapter.read(jsonReader);
                if(entity instanceof ApiResponse){
                    ApiResponse result = (ApiResponse) entity;
                    if(!result.isSuccess()){
                        if(result.getMsg() != null){
                            Log.v(TAG, "convert: " + result.getMsg());
                        }
                        throw new ApiException(result.getMsg());
                    }
                }
                return entity;
            }catch (Exception e){
                e.printStackTrace();
                throw e;
            } finally {
                value.close();
            }
        }
    }

最后使用的使用,创建Retrofit使用addConverterFactory就行了

Retrofit retrofit = new Retrofit.Builder()
                ````
                .addConverterFactory(DsGsonConverterFactory .create(gson))
              ```
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值