Retrofit源码赏析六 —— Converter
前面通过OkHttpCall我们获取到了接口响应,但是这时候拿到的是ResponseBody,而实际使用过程中我们需要的往往是一个实体类,Retrofit通过Converter完成了这一转换。
T body = responseConverter.convert(catchingBody);
Converter由Converter.Factory创建
Converter.Factory
abstract class Factory {
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
从代码结构可以看出Converter作为一个数据转换器,它不仅能转换返回的数据,还能转换我们的请求体
- responseBodyConverter() 把响应数据ResponseBody转换为我们需要的结构。
- requestBodyConverter() 把请求的数据转换为RequestBody。
- stringConverter() 把请求的类型转换为String。
- getParameterUpperBound() 获取泛型第index个参数的上界,比如index=1并且Map<String,? extends Runnable>就返回Runnable。
- getRawType() 获取返回值的原始类型,例如List<? extends Runnable>就返回List。
Converter.Factory只是一个抽象类,实际工作由他的实现类完成,Retrofit为我们默认提供了BuiltInConverters和OptionalConverterFactory。 并且在创建Retrofit的时候也默认添加了这两个工厂。
public Retrofit build() {
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
}
由平台提供的defaultConverterFactories如下
List<? extends Converter.Factory> defaultConverterFactories() {
return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
}
只有在Java8以上才会提供OptionalConverterFactory。
BuiltInConverters
responseBodyConverter()实现比较简单,只能处理ResponseBody,Void,Unit(kotlin)三种类型。
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
if (checkForKotlinUnit) {
try {
if (type == Unit.class) {
return UnitResponseBodyConverter.INSTANCE;
}
} catch (NoClassDefFoundError ignored) {
checkForKotlinUnit = false;
}
}
return null;
}
首先会根据我们声明的不同的返回类型创建不同的Converter,对于ResponseBody,一般情况下是字符流形式返回,这种情况下会返回BufferingResponseBodyConverter,当我们下载文件时,我们需要以二进制流形式返回,这种情况下,我们会在方法上声明@Streaming注解,当Retrofit读取到此注解的时候就会为我们返回StreamingResponseBodyConverter。
//BufferingResponseBodyConverter
public ResponseBody convert(ResponseBody value) throws IOException {
return Utils.buffer(value);
}
//StreamingResponseBodyConverter
public RequestBody convert(RequestBody value) {
return value;
}
Void和Unit(kotlin)的处理都比较简单,他们对应的Converter主要是为了调用ResponseBody#close()方法,安全关闭。
static final class UnitResponseBodyConverter implements Converter<ResponseBody, Unit> {
static final UnitResponseBodyConverter INSTANCE = new UnitResponseBodyConverter();
public Unit convert(ResponseBody value) {
value.close();
return Unit.INSTANCE;
}
}
requestBodyConverter()方法中只是判断了请求类型是不是RequestBody,对于RequestBody的请求类型会原样处理。
public Converter<?, RequestBody> requestBodyConverter(Type type Annotation[] pa,Annotation[] ma,Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
OptionalConverterFactory
Optional是在Java8中引入解决NullPointerExceptions问题的类。所以OptionalConverterFactory只有在Java8以上或者Android Api24以上才会引入。
final class OptionalConverterFactory extends Converter.Factory {
static final Converter.Factory INSTANCE = new OptionalConverterFactory();
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(type) != Optional.class)return null;
Type innerType = getParameterUpperBound(0, (ParameterizedType) type);
Converter<ResponseBody, Object> delegate = retrofit.responseBodyConverter(innerType, annotations);
return new OptionalConverter<>(delegate);
}
}
OptionalConverterFactory只是重写了responseBodyConverter()方法。
首先判断类型是否为Optional,对于非法类型直接返回null,然后获取Optional所包装的真实类型innerType,通过这个innerType在retrofit中查找能处理它的Converter,找到之后通过Optional将其包装为OptionalConverter。
static final class OptionalConverter<T> implements Converter<ResponseBody, Optional<T>> {
public Optional<T> convert(ResponseBody value) throws IOException {
return Optional.ofNullable(delegate.convert(value));
}
}
可以看出OptionalConverterFactory仅仅只做了下拆除Optional包装,对于真正的类型转换还需要其他的Converter,也就是说到目前未知我们只能处理ResponseBody,Void,Unit(kotlin)三种类型,但是实际项目中我们经常需要直接转换为业务实体类,所幸Retrofit支持自定义Converter并且已经为我们实现了很多ResponseBody转实体类的Converter,以配个Gson使用的GsonConverterFactory为例。
GsonConverterFactory
GsonConverterFactory不是Retrofit核心库提供的类,所以首先需要额外引入依赖。
com.squareup.retrofit2:converter-gson:2.9.0
然后注册进Retrofit
addConverterFactory(GsonConverterFactory.create(gson))
GsonConverterFactory实现了responseBodyConverter()和requestBodyConverter()方法。
public final class GsonConverterFactory extends Converter.Factory {
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] pa,Annotation[] ma,Retrofit retrofit){
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
与BuiltInConverters和OptionalConverterFactory不同的是,它没有判断类型type,来者不拒,全部交给Gson处理。
GsonResponseBodyConverter
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
//省略部分代码
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
return = adapter.read(jsonReader);
}
}
convert内部通过gson的newJsonReader()方法获取JsonReader对象,然后通过TypeAdapter获取对应的类型。
GsonRequestBodyConverter
final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
//省略部分代码
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());
}
}
通过Gson将请求参数写入Buffer,然后通过RequestBody.create()创建RequestBody对象并返回。
转载自:https://juejin.cn/post/7112034017905967112