Retrofit 源码解析
Contents
Retrofit 是 square 推出用来请求 RESTful 风格 API 的网络库,可以让开发人员快速开发 RESTful 风格的应用。
本文基于
retrofit2.5.0进行分析。
简单使用
我们先从官方的例子中了解一下怎么使用,相信对于 Android 开发者来说,使用已经非常熟练了。
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
repos.execute();
例子中先创建了 API 接口,然后创建了 Retrofit 实例,接着调用 retrofit.create 创建了接口实现类,最后就是我们调用网络请求获取数据了。 retrofit 基本的用法就是这样。
下面我们就来一步一步分析
Retrofit.build
Retrofit 使用建造者模式创建 API,我们从 Retrofit.build 开始分析
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// 设置 OkHttp
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 设置回调
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
// 添加适配器
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 添加数据转换器
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
在创建 Retrofit 时,先设置了 callFactory ,如果没有手动设置,那么 Retrofit 默认会帮你设置为 OkHttpClient 。
接下来设置 callbackExecutor ,如果没有设置则会调用 platform 的 defaultCallbackExecutor , platform 会根据不同的平台返回不同的 Executor , Android 中返回的是 MainThreadExecutor 。
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
在 MainThreadExecutor 中看到 Callback 默认是在主线程的。顺便提一下 platform 是在 Builder 的构造方法中设置的,属于太细节,这里就不去分析了。
可以看到接下来设置的 defaultCallAdapterFactory 返回的是 ExecutorCallAdapterFactory 。
最后设置 converterFactories ,这是用来把服务器结果转换成我们期望的格式,通常我们会转换成 JSON 。 Retrofit 也内置了 BuiltInConverters ,它只能转换 Void 、 Buffer 、 Stream 类型。
总结一下 Retrofit#build 干了什么
callFactory没有设置默认为OkHttpClientcallbackExecutorAndroid 平台默认是MainThreadExecutor,用来回调请求结果的。callAdapterFactoriesAndroid 平台默认添加ExecutorCallAdapterFactory,用来把Retrofit.Call转换成其他的Call这里其实是OkHttpCall。这样Retrofit.Call就和别的Call高度解耦了。converterFactories默认添加BuiltInConverters,用来把请求结果转换成对应的JavaBean
Retrofit.create
Retrofit 的实例创建好了,需要调用 create 来创建接口的实现类。
public <T> T create(final Class<T> service) {
...
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
在 create 方法中使用了动态代理创建接口的实现类,当我们调用接口中的方法会执行 invoke ,第一参数就是调用的对象,第二个参数就是调用对象的某个方法,第三个参数就是方法需要的参数。如果调用的类是 Object 和 Java8 的方法,则直接调用。最后返回 loadServiceMethod(method).invoke(args != null ? args : emptyArgs) 。
loadServiceMethod
接下来我们来看最有料的 loadServiceMethod
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
loadServiceMethod 为了提高性能做了缓存,不然每次都要查找多费时间。最后调用 ServiceMethod.parseAnnotations 生成 ServiceMethod 并返回了。这样看来重点在 parseAnnotations 中,跟进去看看。
parseAnnotations
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 省略一些检查判断...
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
首先调用了 RequestFactory.parseAnnotations 生成 RequestFactory ,在 RequestFactory.parseAnnotations 中会根据注解解析出请求方法,请求 URL ,请求头,请求体,表单等信息,代码如下。
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
// 获取方法上的注解
this.methodAnnotations = method.getAnnotations();
// 获取参数类型
this.parameterTypes = method.getGenericParameterTypes();
// 获取参数上的注解,一个参数可能有多个注解,所以是个二维数组
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
RequestFactory(Builder builder) {
method = builder.method;
baseUrl = builder.retrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
headers = builder.headers;
contentType = builder.contentType;
hasBody = builder.hasBody;
isFormEncoded = builder.isFormEncoded;
isMultipart = builder.isMultipart;
parameterHandlers = builder.parameterHandlers;
}
然后调用了 HttpServiceMethod.parseAnnotations ,生成 ServiceMethod ,接下来看一下 HttpServiceMethod.parseAnnotations 是怎么构建 ServiceMethod 的。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
...
Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
HttpServiceMethod.parseAnnotations 先调用了 createCallAdapter 找到对应的 callAdapter 并取出返回值的类型,然后调用 createResponseConverter 把返回值类型传递进去,找到对应的 responseConverter 、最后把它们和 callFactory 、 requestFactory 封装成 serviceMethod 。
接下来看看 CallAdapter 和 responseConverter 是怎么被创建的
createCallAdapter
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
// 省略部分代码
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
}
// Retrofit#callAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
// Retrofit#nextCallAdapter
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
// 省略部分代码
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;
}
}
}
createCallAdapter 方法调最后调用的是 nextCallAdapter ,它会遍历 callAdapterFactories 根据注解和返回值类型查找合适的 CallAdapter 。在构造 Retrofit 时,我们可以通过 addCallAdapterFactory 往 callAdapterFactories 添加需要的适配器。
createResponseConverter
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
// Retrofit#responseBodyConverter
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
// Retrofit#nextResponseBodyConverter
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
...
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;
}
}
// ....
}
和 createCallAdapter 一样的套路,遍历 converterFactories 根据注解和返回值类型查找合适的 Converter 。
loadServiceMethod 做的就是通过返回值和注解生成 CallAdapter 和 ResponseConverter ,最后构造 HttpServiceMethod 。
invoke
loadServiceMethod 最后返回的是 HttpServiceMethod ,所以最后调用的 invoke ,是 HttpServiceMethod 的 invoke 。
// HttpServiceMethod
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
invoke 调用了 callAdapter.adapt ,根据之前的分析知道默认的 callAdapterFactories 是 ExecutorCallAdapterFactory , 所以这里的 callAdapter 是 ExecutorCallAdapterFactory 中返回的匿名的 CallAdapter 。代码如下
@Override public @Nullable 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;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
在 adapt 方法中返回了 ExecutorCallbackCall 所以调用接口的方法最后返回的是 ExecutorCallbackCall ,也就是我们调用 Retrofit.create 创建的服务,调用其中的方法,最后面其实调用 ExecutorCallbackCall 。 关于 ExecutorCallbackCall 我们后面还会碰到。
小节一下 Retrofit#create 里做了这么几件事
- 根据动态代理为每个接口方法创建
ServiceMethod - 在
loadServiceMethod中根据注解和方法的返回值的类型,生成requestFactory - 在
HttpServiceMethod.parseAnnotations中根据注解寻找合适的CallAdapter和ResponseConverter。构建ServiceMethod(HttpServiceMethod)。 - 在
HttpServiceMethod#invoke中调用callAdapter.adapt把Retrofit.Call适配成callFactory能调用的请求,也就是OkHttpCall。
执行请求
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
在上小节中,调用 invoke 最后得到的是一个 ExecutorCallbackCall ,其中 delegate 是个 OkHttpCall 我们调用 enqueue 其实调用的是 OkHttpCall 的 enqueue , execute 直接调用了 delegate.execute() ,就不说了。
来看 enqueue 的 onResponse 中,最后的的结果会调用 callbackExecutor.execute ,之前我们分析在 Android 中 这个 callbackExecutor 是 MainThreadExecutor ,所以最后的结果是在主线程中被回调的。
OkHttpCall
接下来我们来看看 OkHttpCall 代码如下
@Override public void enqueue(final Callback<T> callback) {
// ...
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
enqueue 中先调用了 createRawCall ,而 createRawCall 中调用了 callFactory.newCall ,所以最后是调用了 OkHttpClient 的 newCall 来创建 OkHttp 的 Call 。 而 requestFactory.create 来创建 okhttp 的 Request 。这样就把网络请求交给了 OkHttp 。
解析请求结果
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
// ...
try {
T body = responseConverter.convert(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;
}
}
在 OkHttpCall 中请求成功后,会调用 parseResponse 来把服务返回的数据转换成对应的 JavaBean 。 而实际进行转换的是 responseBodyConverter.convert 。
总结
Retrofit通过动态代理创建 API 的实现类。- 通过
callAdapter进行请求的转换。把Retrofit.Call适配成OkHttpCall - 通过
responseConverter进行请求结果的转换。 - 具体的网络请求交给
callFactory。 - 通过
callbackExecutor把请求的结果往主线程切换。 - 通过注解生成
request
总体上讲 Retrofit 实际是对网络框架的一层封装,让其更方便的处理 RESTful 风格的 API。