Retrofit 源码流程解析
主要类介绍 (默认使用默认解析器DefaultCallAdapterFactory)
第一步 解析配置参数流程
Retrofit
ServiceMethod
--> parseAnnotations(retrofit, method)RequestFactory
--> parseAnnotations(retrofit, method)HttpServiceMethod
--> parseAnnotations(retrofit, method, requestFactory) (返回一个CallAdapter对象,核心方法)HttpServiceMethod的内部类类CallAdapted(requestFactory, callFactory, responseConverter, callAdapter)
参数callAdapter来自于retrofit的CallAdapterServiceMethod.invoke(args)
HttpServiceMethod.invoke(args)
OkHttpCall
包装了okhtt3 的Call的具体使用, 提供了enqueue/execute 方法执行网络请求HttpServiceMethod.CallAdapted
--> adapt(call, args) --> retrofit.CallAdapted.adapt(call)DefaultCallAdapterFactory
// --> get() --> adapt(Call<Object> call) get() --> 匿名实现了Call<Object> adapt(Call<Object> call) 方法; CallAdapter.adapt() 的作用是 将 Retrofit 的原始 Call 适配成你需要的调用形式。默认情况下它什么也不做,但通过自定义 CallAdapter(如 RxJava、Coroutines),可以支持更丰富的异步编程范式。
第二步 请求发起调用流程
调用 enqueue() 或 execute() 当用户拿到返回的 Call 对象后,手动调用 enqueue() 或 execute() 时,会直接触发 OkHttpCall 的对应方法:
// 用户代码示例
Call<Response> call = apiService.getData();
call.enqueue(callback); // 或 call.execute();
OkHttpCall
OkHttpCall 是 Retrofit 对 OkHttp 的封装,其核心逻辑如下:
同步请求 execute()
// OkHttpCall.java
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
// 1. 创建或复用 OkHttp 的 Call 对象
call = createRawCall();
}
// 2. 执行同步请求,并解析响应
return parseResponse(call.execute());
}
异步请求 enqueue()
// OkHttpCall.java
@Override public void enqueue(Callback<T> callback) {
okhttp3.Call call;
synchronized (this) {
// 1. 创建或复用 OkHttp 的 Call 对象
call = createRawCall();
}
// 2. 执行异步请求
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
// 3. 解析响应并回调
Response<T> response = parseResponse(rawResponse);
callback.onResponse(OkHttpCall.this, response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callback.onFailure(OkHttpCall.this, e);
}
});
}
最终执行到 OkHttp
核心逻辑如下:
OkHttpCall 内部通过 createRawCall() 创建 OkHttp 的 okhttp3.Call 对象,并委托给它执行请求:
RequestFactory
的create
方法中 主要是将解析后的method和参数列表
封装到Invocation
中,并将Invocation
存储到Okhttp的Reequest的tag属性中,tag是一个HashMap集合; 并最终返回Okhttp的Request对象。
// OkHttpCall.java
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;
}
// RequestFactory.java
okhttp3.Request create(Object[] args) throws IOException {
...
return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
}
流程总结
-
动态代理拦截 → 生成 ServiceMethod 和 OkHttpCall。
-
CallAdapter.adapt() → 默认直接返回 OkHttpCall。
-
用户调用 enqueue()/execute() → 触发 OkHttpCall 的对应方法。
-
OkHttpCall 委托给 OkHttp → 通过 okhttp3.Call 发起实际网络请求。
Retrofit 源码流程跟踪详解
- Retrofit初始化入口
public <T> T getApiService(Class<T> serviceClass) {
return new Retrofit.Builder().baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
// 创建okhttpclient
.client(mOkhttpClient)
.build()
// 通过动态代理创建api
.create(serviceClass);
}
- 调用Retrofit的create方法,传入接口的class对象,创建接口的实现类。
public <T> T create(final Class<T> service) {
validateServiceInterface(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 @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
使用 Proxy.newProxyInstance() 创建代理实例,需要三个参数: (被代理队形是传入的参数 service)
-
类加载器: service.getClassLoader()
-
要代理的接口数组: new Class<?>[] {service}
-
调用处理器: 自定义的 InvocationHandler 实现
- 具体方法片段代码解析
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
这段代码是 Retrofit 动态代理中处理接口方法调用的核心分支逻辑,主要区分和处理两种类型的接口方法:
1. Java 8 默认方法 (Default Method)
判断条件:platform.isDefaultMethod(method)
-
什么是默认方法:Java 8 引入的特性,允许接口中包含带有实现的方法(使用
default
关键字)public interface MyApi { @GET("users") Call<List<User>> getUsers(); // 默认方法 default String getDefaultName() { return "default_name"; } }
-
为什么需要特殊处理:因为这些方法已经有实现,不应该被 Retrofit 转换为 HTTP 请求
-
处理方式:
platform.invokeDefaultMethod(method, service, proxy, args)
- 直接调用接口中的默认方法实现
- 保持默认方法的原有行为不变
2. 普通抽象方法 (常规 Retrofit 接口方法)
判断条件:非默认方法的情况
-
典型特征:带有 Retrofit 注解(如
@GET
,@POST
等)的抽象方法@GET("users/{id}") Call<User> getUser(@Path("id") String userId);
-
处理方式:
loadServiceMethod(method).invoke(args)
loadServiceMethod(method)
:加载或创建方法对应的 ServiceMethod- 解析方法注解(HTTP 方法、路径、参数等)
- 创建适当的调用适配器(如
Call
类型) - 缓存解析结果以提高性能
.invoke(args)
:使用解析后的配置执行实际调用- 构建 HTTP 请求
- 处理参数
- 返回适当的响应类型
设计意义
这种分支处理使得 Retrofit 能够:
- 保持与 Java 8+ 的兼容性:正确处理接口中的默认方法
- 明确区分:哪些方法应该被转换为 HTTP 请求,哪些应该保持原样
- 灵活扩展:通过
Platform
类抽象不同平台(Android、Java 8 等)的特殊处理
实际执行流程示例
对于以下接口:
public interface GitHubService {
// 普通抽象方法 - 会被转换为HTTP请求
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
// 默认方法 - 直接调用实现
default String defaultEndpoint() {
return "https://api.github.com";
}
}
- 调用
listRepos("octocat")
→ 走loadServiceMethod
分支,转换为 HTTP 请求 - 调用
defaultEndpoint()
→ 走invokeDefaultMethod
分支,直接返回 "api.github.com"
DefaultCallAdapterFactory解析器源码
package retrofit2;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Objects;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
import okhttp3.Request;
import okio.Timeout;
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
}
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
delegate.enqueue(
new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(
() -> {
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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
@Override
public boolean isExecuted() {
return delegate.isExecuted();
}
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override
public void cancel() {
delegate.cancel();
}
@Override
public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override
public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override
public Request request() {
return delegate.request();
}
@Override
public Timeout timeout() {
return delegate.timeout();
}
}
}
在 DefaultCallAdapterFactory
的源码中,没有直接看到 T adapt(Call<R> call)
方法的独立定义,这是因为 Retrofit 的 CallAdapter
接口使用了 泛型类型参数,而 DefaultCallAdapterFactory
通过 匿名内部类 的方式实现了 CallAdapter
接口,并将泛型具体化为 Call<?>
。下面我会详细解释:
1. CallAdapter
接口的定义
首先回顾 CallAdapter
接口的原始定义(来自 Retrofit 源码):
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call); // 关键方法!
}
R
:原始响应类型(如Response<User>
)。T
:适配后的返回类型(如Call<User>
、Observable<User>
等)。
2. DefaultCallAdapterFactory
的实现
在 DefaultCallAdapterFactory
中,get()
方法返回了一个 匿名内部类 的 CallAdapter
实例:
return new CallAdapter<Object, Call<?>>() { // 注意泛型参数:R=Object, T=Call<?>
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) { // 这就是 T adapt(Call<R> call) 的实现!
return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
}
};
- 泛型具体化:这里明确指定了
R=Object
和T=Call<?>
,因此adapt()
方法的签名变为Call<Object> adapt(Call<Object> call)
。 - 方法逻辑:
- 如果
executor
为null
,直接返回原始call
(即OkHttpCall
)。 - 如果
executor
存在,返回包装后的ExecutorCallbackCall
(用于切换回调线程)。
- 如果
3. 为什么看起来不像 T adapt(Call<R> call)
?
由于 Java 的泛型擦除和匿名内部类的语法,adapt()
的具体实现被“隐藏”在匿名类中。但本质上:
Call<Object> adapt(Call<Object> call)
就是T adapt(Call<R> call)
的具体实现。- 因为
T
被具体化为Call<?>
,R
被具体化为Object
,所以方法签名看起来不同,但逻辑完全一致。
4. 关键点:adapt()
的作用
在这个实现中,adapt()
方法的主要职责是:
- 线程切换:通过
ExecutorCallbackCall
将回调切换到指定的Executor
(如主线程的HandlerExecutor
)。 - 透明传递:如果不需要线程切换(
executor == null
),直接返回原始Call
对象。
5. 执行流程示例
假设用户定义了一个接口方法:
@GET("/user")
Call<User> getUser();
Retrofit 的处理步骤如下:
- 动态代理调用
invoke()
:- 创建
OkHttpCall
(原始Call
对象)。
- 创建
- 调用
adapt()
:- 如果未设置
executor
,直接返回OkHttpCall
。 - 如果设置了
executor
,返回ExecutorCallbackCall
(包装OkHttpCall
)。
- 如果未设置
- 用户调用
enqueue()
:- 如果是
ExecutorCallbackCall
,会通过executor
切换线程后,再调用OkHttpCall.enqueue()
。
- 如果是
6. 总结
adapt()
的存在:确实实现了,只是以匿名内部类的方式呈现,且泛型被具体化。- 核心逻辑:决定是否包装
Call
对象以实现线程切换。 - 默认行为:如果没有设置
callbackExecutor
,adapt()
直接返回原始Call
,此时enqueue()
/execute()
会直接触发OkHttpCall
的请求。
通过这种设计,Retrofit 保持了默认行为的简洁性,同时允许灵活扩展(如 RxJava 的 CallAdapter
)。