接口多格式数据解析

前因:由于项目功能的增加,所需要接人的后台接口也不只一个,返回格式的差异化也不可避免。

思路:接口返回时我们所必须的值分别是Http status code、HTTP status message or null if unknown、和body。当我们在接收数据时先把数据转换为JsonObject,然后在CallAdapterFactory中转换为指定格式

new Retrofit.Builder()
 .addConverterFactory(CustomGsonConverterFactory.create())
 .addCallAdapterFactory(new LglLiveDataCallAdapterFactory())
 .baseUrl(Constants.BASE_LGL_URL)
 .client(okHttpClient)
 .build()
 .create(LGLApiService.class);

CustomGsonConverterFactory.java

public class CustomGsonConverterFactory extends Converter.Factory {

    private final Gson gson;

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

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

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

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

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

CustomGsonRequestBodyConverter.java

public class CustomGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {

    public 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;

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

    @Override
    public RequestBody convert(T value) {
        return RequestBody.create(MEDIA_TYPE, value.toString());
    }
}

CustomGsonResponseBodyConverter.java

public class CustomGsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private static final String TAG = "CustomGsonResponseBodyC";

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

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

    @Override
    public T convert(ResponseBody value) throws IOException {
        byte[] bytes = value.bytes();
        String jsonString = new String(bytes);
        Reader reader = StringToReader(jsonString);
        JsonReader jsonReader = gson.newJsonReader(reader);
        try {
            return adapter.read(jsonReader);
        } finally {
            reader.close();
            jsonReader.close();
        }
    }

    /**
     * String转Reader
     *
     * @param json
     * @return
     */
    private Reader StringToReader(String json) {
        Reader reader = new StringReader(json);
        return reader;
    }
}

LglLiveDataCallAdapterFactory.java

public class LglLiveDataCallAdapterFactory extends CallAdapter.Factory {

    @Override
    public CallAdapter<?, ?> get(@NonNull Type returnType, @NonNull Annotation[] annotations, @NonNull Retrofit retrofit) {
        if(!(returnType instanceof ParameterizedType)){
            throw new IllegalArgumentException("返回值需为参数化类型");
        }

        if (getRawType(returnType) != LiveData.class) {
            return null;
        }
        Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);

        Type custObservableType = getParameterUpperBound(0,(ParameterizedType)observableType);

        return new LglLiveDataCallAdapter<>(custObservableType);
    }
}

LglLiveDataCallAdapter.java

public class LglLiveDataCallAdapter<R> implements CallAdapter<R, LiveData<LglApiResult<R>>> {
    public static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");

    private final Type responseType;

    public LglLiveDataCallAdapter(Type responseType) {
        this.responseType = responseType;
    }

    @Override
    public Type responseType() {
        return responseType;
    }

    @Override
    public LiveData<LglApiResult<R>> adapt(Call<R> call) {
        AtomicBoolean started = new AtomicBoolean(false);

        return new LiveData<LglApiResult<R>>() {
            @Override
            protected void onActive() {
                super.onActive();
                if (started.compareAndSet(false, true)) {
                    call.enqueue(new Callback<R>() {
                        @Override
                        public void onResponse(Call<R> call, Response<R> response) {
                            LglApiResult apiResult = new LglApiResult<>();
                            apiResult.code = response.code();
                            apiResult.msg = response.message();
                            apiResult.data = null;

                            if (response.isSuccessful()) {
                                ResponseBody responseBody = ResponseBody.create(MEDIA_TYPE, response.body().toString());

                                Gson gson = new Gson();
                                TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(responseType));
                                CustomGsonResponseBodyConverter<?> converter = new CustomGsonResponseBodyConverter<>(gson, adapter);
                                try {
                                    apiResult.data = converter.convert(responseBody);
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }

                            }
                            postValue(apiResult);
                        }

                        @Override
                        public void onFailure(Call<R> call, Throwable t) {
                            LglApiResult<R> apiResult = new LglApiResult<>();
                            apiResult.code = 999;
                            apiResult.msg = t.getMessage();
                            apiResult.data = null;
                            postValue(apiResult);
                        }
                    });
                }
            }
        };
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值