版权申明】非商业目的可自由转载
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/81387328
出自:shusheng007
系列文章
最简单易懂的Retrofit2源码详解
用Retrofit+RxJava2封装优雅的网络请求框架
秒懂Retrofit2之Converter
前两天分析了Retrofit的源码,个人认为其精髓就在于CallAdapter 与Converter的设计上,本文我们就先研究下Converter
的知识,下一篇再研究CallAdapter
。强烈建议先阅读 秒懂Retrofit2之Converter
假设我们不为Retrofit
设置任何Converter
,那么Retrofit
能正常工作吗?有什么限制?先看下面代码:
code1
@POST
@Multipart
Callmethod1(@Part("p") RequestBody rBody);
@POST
Callmethod2(@Body RequestBody rBody);
code2
@POST
@Multipart
Callmethod1(@Part("p") Map rBody);
@POST
Call>method2(@Body User rBody);
code1 是没有添加自定义converter
时可以做的,而code2是添加了GsonConverter
后可以做的。可以发现仅仅使用默认的converter
的话会在使用上存在巨大限制。
对于方法的请求参数来说
使用@Part
,@PartMap
,@Body
标记的参数类型就只能是RequestBody
对于方法的返回结果来说
方法放回结果的泛型参数只支持ResponseBody
与Void
那样对我们的使用来说就麻烦了许多,需要不断的将数据在我们自己的类型与ResponseBody
之间互相转换。而GsonConverterFactory
就是为了将这个数据类型转换的工作自动化而生的。
得益于Gson
的强大,使的 GsonConverterFactory
非常简单,源码也仅仅只有3个类。
我就是通过这个工厂来调用请求转换器requestBodyConverter
与结果转换器responseBodyConverter
的
public final class GsonConverterFactory extends Converter.Factory {
//最常使用的静态工厂方法,使用默认的Gson实例
public static GsonConverterFactory create() {
return create(new Gson());
}
//使用这个工厂方法可以从外部传入Gson对象,我们可以对这个Gson对象做很多配置
public static GsonConverterFactory create(Gson gson) {
...
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@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);
}
}
源码简洁的令人发指,首先由两个静态工厂方法可以获得对象实例,其中一个可以出入一个Gson对象,这就产生了很多想象空间。因为我们可以在外部配置这个Gson
对象的各种属性,关于如何配置,希望你调研一下,肯定又会惊叹于Gson
设计的精妙。剩下两个函数我都不好意思讲了,不然会有侮辱读者智商的嫌疑。
请求转化器
final class GsonRequestBodyConverter implements Converter {
private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson;
private final TypeAdapter adapter;
GsonRequestBodyConverter(Gson gson, TypeAdapter 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());
}
}
结构很清晰,就是将一个T类型的数据value,例如为User
,通过convert()
转化为RequestBody
类型的数据。如果你觉得看不懂,肯定不是看不懂逻辑而是看不懂转换的代码,别装了,承认看不懂不难!那就去研究Gson
吧,少年!
结果转换器
final class GsonResponseBodyConverter implements Converter {
private final Gson gson;
private final TypeAdapter adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
T result = adapter.read(jsonReader);
if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
return result;
} finally {
value.close();
}
}
}
结构仍然很清晰,就是通过convert()
将RequestBody
类型的value数据转换为我们期望的T类型的数据,例如T为User
。如果你又觉得看不懂,肯定不是看不懂逻辑而是看不懂转换的代码,别装了,承认看不懂不难!那就去研究Gson
吧,少女!
目前除了GsonConverter
以外,源码中还包含了很多其他的的转换器,例如jackson
、guave
、java8
、simplexml
等等,当遇到相应的场景时可以使用,如果现存的Converter
不能满足我们的需求,我们就需要自己开发一个转换器了。