站在巨人的肩膀上 -- Retrofit源码解析
Posted 巨头之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了站在巨人的肩膀上 -- Retrofit源码解析相关的知识,希望对你有一定的参考价值。
上一篇 站在巨人的肩膀上 – Retrofit源码解析(一) 主要是从Retrofit使用的基本API角度,去理清源码中大致的流程,可以说Retrofit是对OkHttp框架做了非常完美的封装,使用了大量的设计模式,使得Retrofit成为了一个简单易上手的网络请求框架. 这一篇主要解决上一篇留下来的疑问.
Retrofit源码基于版本2.4.0
1.ServiceMethod.Builder类的build函数,调用createCallAdapter函数是怎么获取到callAdapter的?
从createCallAdapter函数出发,调用到Retrofit类的callAdapter函数
private CallAdapter<T, R> createCallAdapter()
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType))
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
if (returnType == void.class)
throw methodError("Service methods cannot return void.");
Annotation[] annotations = method.getAnnotations();
try
//noinspection unchecked
//遍历 存放网络请求适配器工厂的集合callAdapterFactories,找到合适的网络请求适配器工厂并返回
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
catch (RuntimeException e) // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
callAdapter函数调用nextCallAdapter函数,主要遍历callAdapterFactories这个存放网络请求适配器工厂的集合,获取跟网络请求函数返回值Call<List< Contributor>>相关的网络请求适配器工厂,那callAdapterFactories是在哪里存入适配器工厂? 存入了哪些适配器工厂?
public final class Retrofit
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations)
return nextCallAdapter(null, returnType, annotations);
//
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations)
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//遍历存放网络请求适配器工厂的集合callAdapterFactories,找到合适的网络请求适配器工厂调用其get函数并返回CallAdapter实例
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++)
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null)
return adapter;
...省略无关代码
callAdapterFactories是在Retrofit的构造函数中赋值的, 而Retrofit是通过Build模式创建的, 看Retrofit.Builder类的build函数
public final class Retrofit
public static final class Builder
public Retrofit build()
...省略部分无关代码
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//将MainThreadExecutor装载进ExecutorCallAdapterFactory工厂实例里,并将工厂实例添加进 网络请求适配器工厂的集合里
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
...省略部分无关代码
//Collections.unmodifiableList()函数是将集合转化成只读的
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
//添加网络请求适配器
public Builder addCallAdapterFactory(CallAdapter.Factory factory)
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
看到callAdapterFactories存入开发者自行添加进去的网络请求适配器工厂,还存入该平台默认的网络请求适配器工厂,此处是android平台,对应的网络请求适配器工厂为ExecutorCallAdapterFactory, 还记得我们在创建Retrofit时调用了.addCallAdapterFactory(RxJavaCallAdapterFactory.create()),所以此处自行添加的网络请求适配器工厂是RxJavaCallAdapterFactory.
现在也就找到callAdapterFactories是在Retrofit.Builder的build函数中存入适配器工厂的,存入了两个适配器工厂,分别是ExecutorCallAdapterFactory和RxJavaCallAdapterFactory.
那上面说的 “获取跟网络请求函数返回值Call<List< Contributor>>相关的网络请求适配器工厂”,获取到的就应该是ExecutorCallAdapterFactory和RxJavaCallAdapterFactory其中之一
在Retrofit类的nextCallAdapter函数中,通过遍历callAdapterFactories集合,取出网络请求适配器工厂并调用自身的get函数,我们看下ExecutorCallAdapterFactory和RxJavaCallAdapterFactory这两个类的get函数
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit)
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
//请求函数的返回值必须是 Observable或Single或Completable
//否则返回null
if (rawType != Observable.class && !isSingle && !isCompletable)
return null;
if (isCompletable)
return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
由于我们在上篇文章中写的网络请求函数的返回值是 “Call<List< Contributor>>”, 那RxJavaCallAdapterFactory的get函数中getRawType(returnType)拿到的Class类型就是Call,不满足判断条件, 所以此处会返回null, 因此不是RxJavaCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit)
if (getRawType(returnType) != Call.class)
return null;
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>()
@Override public Type responseType()
return responseType;
//这里传入的call = OkHttpCall实例,callbackExecutor = MainThreadExecutor实例
@Override public Call<Object> adapt(Call<Object> call)
return new ExecutorCallbackCall<>(callbackExecutor, call);
;
ExecutorCallAdapterFactory类的get函数中,通过getRawType获取到的是Call类型,满足条件,那么满足适配器工厂条件的就是ExecutorCallAdapterFactory类,其get函数中创建了CallAdapter的匿名内部类并返回,那此处的匿名内部类实例就是ServiceMethod.Builder类的createCallAdapter函数中retrofit.callAdapter( )获取到的值,也就是在ServiceMethod.Builder类的build函数调用createCallAdapter函数返回的就是这个匿名内部类
2.ServiceMethod.Builder类的build函数,调用createResponseConverter函数是怎么生成responseConverter的?
这里生成的responseConverter的代码流程跟上面1类似
从createResponseConverter函数出发,调用到Retrofit类的nextResponseBodyConverter函数
private Converter<ResponseBody, T> createResponseConverter()
Annotation[] annotations = method.getAnnotations();
try
//遍历 存放数据转换器工厂的集合converterFactories,找到合适的数据转换器工厂并返回
return retrofit.responseBodyConverter(responseType, annotations);
catch (RuntimeException e) // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
public final class Retrofit
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations)
return nextResponseBodyConverter(null, type, annotations);
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations)
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
//遍历 存放数据转换器工厂的集合converterFactories,找到合适的数据转换器工厂并返回
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++)
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null)
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
...省略无关代码
在nextResponseBodyConverter函数中,主要遍历converterFactories这个存放数据转换器工厂的集合,获取跟网络请求函数返回值Call<List< Contributor>>相关的数据转换器工厂,那converterFactories在哪里存入数据转换器工厂? 存入了哪些数据转换器工厂?
converterFactories是在Retrofit的构造函数中赋值的, 而Retrofit是通过Build模式创建的, 看Retrofit.Builder类的build函数
public final class Retrofit
public static final class Builder
public Retrofit build()
//...省略无关代码
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
//将默认的数据转换器装载进工厂实例里,添加数据转换器工厂进集合里
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
//Collections.unmodifiableList()函数是将集合转化成只读的
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
//添加数据转化器工厂
public Builder addConverterFactory(Converter.Factory factory)
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
看到converterFactories存入开发者自行添加进去的数据转换器工厂,还存入该平台默认的数据转换器工厂BuiltInConverters类的实例, 还记得我们在创建Retrofit时调用了.addConverterFactory(GsonConverterFactory.create()),所以此处自行添加的数据转换器工厂是GsonConverterFactory.
现在也就找到converterFactories是在Retrofit.Builder的build函数中存入转换器工厂的,存入了两个数据转换器工厂,分别是BuiltInConverters和GsonConverterFactory.
那上面说的 “获取跟网络请求函数返回值Call<List< Contributor>>相关的数据转换器工厂”,获取到的就应该是BuiltInConverters和GsonConverterFactory其中之一
在Retrofit类的nextResponseBodyConverter函数中,通过遍历converterFactories集合,取出数据转换器工厂并调用自身的responseBodyConverter函数,我们看下BuiltInConverters和GsonConverterFactory这两个类的responseBodyConverter函数
final class BuiltInConverters extends Converter.Factory
@Override
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;
return null;
此处的type就是根据网络请求函数返回值Call<List< Contributor>> 获取到的响应数据类型,即type 等于java.util.List<com.example.retrofit.SimpleService$Contributor>,所以BuiltInConverters类的responseBodyConverter函数经过判断会返回null,显然不是这个系统默认的数据转换器工厂
public final class GsonConverterFactory extends Converter.Factory
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit)
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
根据type等于java.util.List<com.example.retrofit.SimpleService$Contributor>,返回的应该是GsonConverterFactory这个数据转换器工厂,在其responseBodyConverter函数中返回GsonResponseBodyConverter类的实例,GsonResponseBodyConverter是负责将响应数据转化为开发者指定的Java类
因此,在ServiceMethod.Builder类的build函数调用createResponseConverter函数返回的就是GsonResponseBodyConverter类的实例, 即responseConverter就是GsonResponseBodyConverter类的实例
3.OkHttpCall类的createRawCall函数中的call的具体实现类是哪个? 内部怎么实现的?
final class OkHttpCall<T> implements Call<T>
private okhttp3.Call createRawCall() throws IOException
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null)
throw new NullPointerException("Call.Factory returned null.");
return call;
createRawCall函数中的call是通过调用ServiceMethod类的toCall函数生成的,看toCall函数
final class ServiceMethod<R, T>
okhttp3.Call toCall(@Nullable Object... args) throws IOException
//...省略无关代码
//callFactory = OkHttpClient,该OkHttpClient是在Retrofit.Buidler的build函数中进行设置值的
//所以这里的okhttp3.Call来源于OkHttp.RealCall类的实例
return callFactory.newCall(requestBuilder.build());
callFactory是在ServiceMethod的构造函数中被赋值,其值来自于Retrofit类,回到Retrofit.Builder类的build函数中
public final class Retrofit
public static final class Builder
public Retrofit build()
//开发者是否传入OkHttpClient实例,未传入则创建
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null)
callFactory = new OkHttpClient();
return new Retrofit(callFactory, baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor,
validateEagerly);
public Builder callFactory(okhttp3.Call.Factory factory)
this.callFactory = checkNotNull(factory, "factory == null");
return this;
callFactory变量就是在此处被初始化的, 在创建Retrofit时,如果开发者未传入okhttp3.Call.Factory类的实现实例, 则会赋予系统默认的OkHttpClient,所以callFactory实际就是OkHttpClient实例.
接着回到ServiceMethod类的toCall函数,callFactory.newCall() 不就等于OkHttpClient.newCall(), 对OkHttp框架熟悉的话,是不是觉得似曾相似
public class OkHttpClient implements Cloneable, Factory, okhttp3.WebSocket.Factory
public Call newCall(Request request)
return RealCall.newRealCall(this, request, false);
那么OkHttpCall类的createRawCall函数中的call也就是此处生成的RealCall实例. 从这可以看出,OkHttpCall类是通过OkHttp框架来发起异步/同步的请求
4.OkHttpCall类的enqueue函数和execute函数中调用的parseResponse(rawResponse)函数,内部是怎么解析响应数据的?
final class OkHttpCall<T> implements Call<T>
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
//根据服务端返回的响应码进行判断并处理
int code = rawResponse.code();
if (code < 200 || code >= 300)
try
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
finally
rawBody.close();
if (code == 204 || code == 205)
rawBody.close();
return Response.success(null, rawResponse);
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try
//将响应数据转化为 网络请求函数中定义的返回类型
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
catch (RuntimeException e)
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
看上面的代码,核心在serviceMethod.toResponse这一句, 接着往下看
final class ServiceMethod<R, T>
R toResponse(ResponseBody body) throws IOException
return responseConverter.convert(body);
这里的responseConverter不就是上面第2个问题中获取到的GsonResponseBodyConverter类的实例,而GsonResponseBodyConverter内部是用了Gson框架来解析数据.
final class<以上是关于站在巨人的肩膀上 -- Retrofit源码解析的主要内容,如果未能解决你的问题,请参考以下文章