一、背景 为什么要自定义Converter
Retrofit官方给了以下几个常用的转换库
Gson: com.squareup.retrofit2:converter-gson
Jackson: com.squareup.retrofit2:converter-jackson
Moshi: com.squareup.retrofit2:converter-moshi
Protobuf: com.squareup.retrofit2:converter-protobuf
Wire: com.squareup.retrofit2:converter-wire
Simple XML: com.squareup.retrofit2:converter-simplexml
Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars
这对于一般的使用来说确实够用了,但是如果我们对安全性要求比较高,或者编码不太一样的话,这些库就没法使用了,于是我们就需要自定义ConverterFactory。Retrofit已经为我们提供了自定义ConverterFactory的接口,我们只需要实现它给的接口即可,首先新建一个类继承Converter.Factory,这里也用到了Gson是因为项目需要解密之后是json字符串。
public final class DecodeConverterFactory extends Converter.Factory {
public static DecodeConverterFactory create() {
return create(new Gson());
}
public static DecodeConverterFactory create(Gson gson) {
return new DecodeConverterFactory(gson);
}
private final Gson gson;
private DecodeConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new DecodeResponseBodyConverter<>(adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] annotations,Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new DecodeRequestBodyConverter<>(gson, adapter);
}
}
然后我们需要自定义responseBodyConverter和requestBodyConverter,这里我们发送请求的时候不需要加密,接收请求的时候需要解密,具体代码如下
public class DecodeResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final TypeAdapter<T> adapter;
DecodeResponseBodyConverter(TypeAdapter<T> adapter) {
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
//解密字符串
return adapter.fromJson(EncryptUtils.decode(value.string()));
}
}
public class DecodeRequestBodyConverter<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;
DecodeRequestBodyConverter(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.flush();
return RequestBody.create(MEDIA_TYPE,buffer.readByteString());
}
}