第二篇:Retrofit调用流程图和使用到的设计模式 - wlrhnh - 博客园
Retrofit分析-漂亮的解耦套路Retrofit分析-漂亮的解耦套路 - 简书
从架构角度看Retrofit的作用、原理和启示从架构角度看Retrofit的作用、原理和启示 - 简书
Retrofit实现原理——函数解析、网络请求和数据转换在前面分析中,我们知道了Retrofit的整体工作流程,就是Retrofit用动态代理生成Call网络请求对象,在这个过程中,用适配器把Retrofit底层的retrofit2.Call对象转换为INetApiService中定义的Call网络请求对象(如Flowable)。
问题是,Retrofit具体是如何知道了INetApiService中定义的Call网络请求对象,如何实现网络请求,以及如何执行的数据转换呢?
具体过程如下; 首先,根据INetApiService中定义的函数,解析函数,得到函数的具体定义,并生成对应的ServiceMethod(会提前从缓存中获取,没有了才创建,提高效率)。
然后,根据这个ServiceMethod,实现一个OkHttpCall的Call对象,负责在Retrofit底层实现网络访问。
其中,在网络访问返回了网络数据时,根据ServiceMethod实现数据转换。 最后,利用上一小节中匹配的适配器,把OkHttpCall对象转换为INetApiService要求的Call网络请求对象。
所以,我们要了解的就是函数解析、网络请求和数据转换这三个动作,至于最后的适配转换,在上一节中已经分析过了。
1. 函数解析 在接口函数里,用注解描述了输入参数,用Java对象定义了返回值类型,所以对输入参数和返回值,ServiceMethod采取了不同的方式去处理。输入参数 输入参数是用来描述url的,它的处理相对简单,ServiceMethod会根据反射得到的Method,取得Annotation注解信息,这些注解是Retrofit自己预定义好的(retrofit2.http.*),ServiceMethod根据预先的定义,直接判断注解所属的逻辑分支,在有网络请求时分情况进行处理,就能得到目标url,http请求头等数据。返回值 返回值是需要用CallAdapter去适配的,所以核心在于生成对应的CallAdapter。 在Retrofit生成Call网络工作对象时,她通过动态代理获取到了接口函数的Method定义,从这个Method中可以获取函数定义的返回对象类型,由于这个转换是需要CallAdapterFactory生产CallAdapter对象去实现,而Retrofit事先并不知道要使用哪个Factory,所以她是遍历所有的CallAdapterFactory,根据目标函数的返回值类型,让每个Factory都去尝试生产一个CallAdapter,哪个成功就用哪个。
2. 网络请求 OkHttpCall继承的retrofit2.Call接口是为了依赖倒置解耦的,真正的网络请求是由OkHttpCall内部引用的okhttp3.call处理的,这个okhttp3.call是 借道ServiceMethod获取的Retrofit中的callFactory,也就是Retrofit中的OkHttpClient。
整个引用链条是这样的: OkHttpCall--okhttp3.call --> ServiceMethod--callFactory --> Retrofit.build()--callFactory//(如未扩展赋值)new OkHttpClient(); --> Retrofit.Builder().client(mClient)//(可能有扩展赋值)扩展过的OkHttpClient
最终的网络请求是由OkHttpCall调用OkHttpClient发出的,调用和回调等过程,也就是在OkHttpCall中处理的。
网络请求的生成过程中,为了使用接口函数中定义的参数,OkHttpCall会调用ServiceMethod来生成Request请求对象,再交给OkHttpCall去处理。
3. 数据转换 因为回调是在OkHttpCall中处理的,所以对回调数据的转换也在OkHttpCall中触发,为了符合接口函数中定义的返回数据类型,OkHttpCall会调用ServiceMethod来转换Response返回数据对象。
OkHttpCall对返回的网络数据,会调用一个serviceMethod.toResponse(ResponseBody body)函数,函数中执行的是:
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
这个函数可以把原始的okhttp3. ResponseBody数据转换为INetApiService接口中要求的数据类型(如BizEntity类型)。 从代码可以看出,实现数据转换的核心对象其实是responseConverter,这个Converter实际上要依次经过Retrofit的建造和ServiceMethod的建造后,才能确定下来的。
Retrofit建造时添加数据转换工厂 Retrofit里有converterFactries列表,这是在我们初始化Retrofit实例时添加的
//retrofit对象
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Config.DOMAIN)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(YourConverterFactory.create())//添加自定义Converter
.build();
ServiceMethod建造时设定数据转换器 ServiceMethod在建造时,就已经确定了对应的是INetApiService中的哪个函数,所以需要明确设定自己的Converter转换对象
public ServiceMethod build() {
...
responseConverter = createResponseConverter();
...
}
这需要调用Retrofit
private Converter createResponseConverter() {
...
retrofit.responseBodyConverter(responseType, annotations);
}
Retrofit会在自己的转换器工厂列表中遍历每个ConverterFactory,尝试根据ServiceMethod所对应的目标数据类型,找到Converter数据转换类
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter) converter;
}
}
以Gson转换为例,GsonConverterFactory会通过getAdapter来尝试匹配目标数据类型:
public TypeAdapter getAdapter(TypeToken type) {...}
如果可以匹配,那么前面调用serviceMethod.toResponse(ResponseBody body)函数时,会调用
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
在调用这段代码时,其实就是调用了Gson中最终执行数据转换的代码:
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
总结来说,Retrofit在类的单一职责方面分隔的很好,OkHttpCall类只负责网络交互,凡是需要知道函数定义的,都交给ServiceMethod类去处理,而ServiceMethod类对使用者不公开,因为Retrofit是个外观模式,而所有需要扩展的都在Retrofit的建造者中实现,他们的分工大概是这样的:
Android Retrofit 2.0 的详细 使用攻略(含实例讲解)Carson带你学Android:网络请求库Retrofit使用教程(含实例讲解) - 简书
Retrofit源码解析流程图只有如下一张图
Retrofit源码解析流程图_ForgetSky的博客-CSDN博客
Retrofit2之CallAdapter和Converter_weixin_34274029的博客-CSDN博客
需要搞明白如下问题:
CallAdapterFactory
是如何起作用的?ConverterFactory
是如何起作用的?
StringCallAdapterFactory
和StringCallAdapter
public class StringCallAdapterFactory extends CallAdapter.Factory {
@Nullable
@Override
public CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if(returnType == String.class)
return new StringCallAdapter();
return null;
}
class StringCallAdapter implements CallAdapter{
@Override
public Type responseType() {
return String.class;
}
@Override
public String adapt(Call call) {
try {
return call.execute().body();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
}
复制代码
定义StringConverterFactory
和StringConverter
public class StringConverterFactory extends Converter.Factory {
@Nullable
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == String.class) {
return new StringConverter();
}
return null;
}
class StringConverter implements Converter {
@Override
public String convert(ResponseBody value) throws IOException {
return value.string();
}
}
}
复制代码
通过自定义CallAdapter和Convert,
首先会执行到Adapter的responseType,返回为我们想要的自定义的String.class
converter通过CallAdapter的返回值String.class,完成后续的请求response结果的转换。