Retrofit源码赏析六 —— Converter

·  阅读 594
Retrofit源码赏析六 —— Converter

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

前面通过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对象并返回。

分类:
Android
标签:
分类:
Android
标签:
收藏成功!
已添加到「」, 点击更改