Retrofit源码解析
更新: 3/18/2026 字数: 0 字 时长: 0 分钟
基本使用
这里关于Retrofit的基本使用不多赘述了,包括结合rxjava,gson等等,这里给一个简单的demo:
interface ApiService {
@GET("getUserData")
fun getUserData(): Call<ResponseBody>
}
fun main() {
val retrofit = Retrofit.Builder()
.baseUrl("https://mockapi.eolinker.com/9IiwI82f58c23411240ed608ceca204b2f185014507cbe3/")
.build()
val service = retrofit.create(ApiService::class.java)
val call: Call<ResponseBody> = service.getUserData()
call.enqueue(object : Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
val userBean = response.body()?.string()
println("userBean: $userBean")
}
override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
println("onFailure: $t")
}
})
}源码分析
Retrofit.create()
看下代码:
public <T> T create(final Class<T> service) {
// 校验接口的合法性
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() {
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) {
// 如果外部调用的是 Object 中声明的方法的话则直接调用
// 例如 toString()、hashCode() 等方法
return method.invoke(this, args);
}
// 空参数的处理,直接转成空数组
args = args != null ? args : emptyArgs;
Reflection reflection = Platform.reflection;
// 根据 method 是否默认方法来决定如何调用
return reflection.isDefaultMethod(method)
? reflection.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(service, method).invoke(proxy, args);
}
});
}这里的核心就是这里所实现的动态代理模式了,我们来详细看看:
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class<?>[] {service},
new InvocationHandler() { ... });这个是创建动态代理对象的标准写法,Proxy.newProxyInstance(...)有三个参数:
- 类加载器
service.getClassLoader()用接口本身的类加载器来加载代理类。
比如 ApiService 是由哪个 ClassLoader 加载的,代理类就尽量用同一个。
- 代理要实现哪些接口
这里的意思是代理要实现哪些接口,这里就是service接口。如果 service 是 ApiService.class,那么返回的对象运行时就相当于:
class $Proxy0 implements ApiService所以我们拿到的api的类型才是ApiService。
- InvocationHandler
这里是最关键的地方,你对代理对象的任何方法调用,都会进到这里:
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable参数含义:
proxy:当前代理对象本身method:你调用的哪个方法args:调用方法时传入的参数
通过动态代理,Retrofit会将我们对ApiService的调用操作转发给InvocationHandler来完成。这样在后续会通过反射拿到我们在声明getUserData()时标注的各个配置项等信息,再将这些配置项拼接为Okhttp的一个网络请求。当调用call.enqueue时就会触发InvocationHandler去发起Okhttp网络请求。
Retrofit会根据method是否是默认方法来决定,如果是默认方法就调用接口自身的默认实现,否则就走loadServiceMethod(method)方法,看一下这个方法:
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
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;
}- 将接口方法的method转为ServiceMethod对象,包含了接口方法的具体信息
- 因为单个接口方法可能会先后被调用许多次,所以放到serviceMethodCache中复用
ServiceMethod
ServiceMethod是个抽象类,他的直接子类只有一个HttpServiceMethod,这个类也是一个抽象类,其包含两个泛型声明,ResponseT 表示的是接口方法返回值的外层包装类型,ReturnT 表示的是我们实际需要的数据类型。例如,对于 fun getUserData(): Call<UserBean> 方法,ResponseT 对应的是 Call,ReturnT 对应的是 UserBean。
HttpServiceMethod实现了invoke方法,并将操作转交给了另一个抽象方法adapt来完成。可以看到,即使我们为接口方法声明的返回值类型是 Observable<UserBean>,invoke 方法内部其实还是需要创建出一个 Call 对象的,HttpServiceMethod 只是把 Call 转换为 Observable 的这个过程交由了 adapt 方法来完成
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
···
}再来看看HttpServiceMethod.parseAnnotations()方法:
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
//是否是 Suspend 函数,即是否以 Kotlin 协程的方式来进行请求
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
//省略 Kotlin 协程的一些处理逻辑
} else {
adapterType = method.getGenericReturnType();
}
//重点1
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
//拿到包装类内部的具体类型,例如,Observable<UserBean> 内部的 UserBean
//responseType 不能是 okhttp3.Response 或者是不包含具体泛型类型的 Response
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(
method,
"'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response<String>)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
//重点2
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
//重点3
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
//省略 Kotlin 协程的一些处理逻辑
···
}
···
}parseAnnotations 方法的主要逻辑是:
- 先通过
createCallAdapter(retrofit, method, adapterType, annotations方法拿到 CallAdapter 对象,CallAdapter 就用于实现接口方法的返回值包装类处理逻辑。例如,getUserData()方法的返回值包装类类型如果是Call,那么返回的 CallAdapter 对象就对应 DefaultCallAdapterFactory 包含的 Adapter;如果是 Observable,那么返回的就是 RxJava2CallAdapterFactory 包含的 Adapter - 再通过
createResponseConverter(retrofit, method, responseType)方法拿到 Converter 对象,Converter 就用于实现接口方法的返回值处理逻辑。例如,getUserData()方法的目标返回值类型如果是 ResponseBody,那么 Converter 对象就对应 BuiltInConverters;如果是 UserBean,那么就对应 GsonConverterFactory - 根据前两个步骤拿到的值,构造出一个 CallAdapted 对象并返回
再来看看这个CallAdapted对象:
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call);
}
}这里的这个CallAdapted正式HttpServiceMethod的子类,在以上步骤中已经找到了可以实现将 Call 转换为 Observable 的 CallAdapter 了,所以对于 CallAdapted 来说,其 adapt 方法会直接将 Call 提交给 CallAdapter,由其去实现这种转换过程。
OkhttpCall
这是实际发起Okhttp请求的地方。当我们调用 fun getUserData(): Call<ResponseBody> 方法时,返回的 Call 对象实际上是 OkHttpCall 类型,而当我们调用 call.enqueue(Callback)方法时,enqueue 方法就会发起一个 OkHttp 请求,传入的 retrofit2.Callback 对象就会由 okhttp3.Callback本身收到回调时再进行中转调用。
final class OkHttpCall<T> implements Call<T> {
private final RequestFactory requestFactory;
private final Object[] args;
private final okhttp3.Call.Factory callFactory;
private final Converter<ResponseBody, T> responseConverter;
private volatile boolean canceled;
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
@GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
private @Nullable Throwable creationFailure;
@GuardedBy("this")
private boolean executed;
@Override
public void enqueue(final Callback<T> callback) {
···
okhttp3.Call call;
···
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) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@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) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
···
}总结
- 首先,我们通过
retrofit.create(ApiService::class.java)得到一个 ApiService 的动态实现类,这是通过 Java 原生提供的Proxy.newProxyInstance代表的动态代理功能来实现的。在拿到 ApiService 的实现类后,我们就可以直接调用 ApiService 中声明的所有方法了 - 当我们调用了
service.getUserData()方法时,Retrofit 会将每一个接口方法都抽象封装为一个 ServiceMethod 对象并缓存起来,我们的操作会转交给 ServiceMethod 来完成,由 ServiceMethod 来负责返回我们的目标类型,对应的是serviceMethod.invoke(Object[] args)方法,args 代表的是我们调用接口方法时需要传递的参数,对应本例子就是一个空数组 - ServiceMethod 使用到了工厂模式,由于网络请求最终的请求方式可能是多样化的,既可能是通过线程池来执行,也可能是通过 Kotlin 协程来执行,使用工厂模式的意义就在于可以将这种差异都隐藏在不同的 ServiceMethod 实现类中,而外部统一都是通过
parseAnnotations方法来获取 ServiceMethod 的实现类 - ServiceMethod 具有一个唯一的直接子类,即 HttpServiceMethod。HttpServiceMethod 自身已经找到了可以将 Call 转换为 Observable,ResponseBody 转换为 UserBean 的转换器,其
invoke方法会构建出一个 OkHttpCall 对象,然后转发给抽象方法adapt,由adapt来发起实际的网络请求 - 而不管外部的接口方法返回值类型是不是
Observable<UserBean>,最终的网络请求都是需要通过 OkHttpCall 来发起,HttpServiceMethod 依靠找到的转换器将 OkHttpCall 给隐藏在了内部
接口方法如何解析的
再来看看Retrofit是如何把interface内部的方法转化为一个个实际的 GET、POST、DELETE 等各式各样的网络请求的。这个过程在 ServiceMethod 的 parseAnnotations 方法中就已经完成的了,对应的是 RequestFactory.parseAnnotations(retrofit, method)方法:
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Class<?> service, Method method) {
// 重点
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, service, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object instance, Object[] args);
}Retrofit是依靠Okhttp进行实际的网络请求,而Okhttp是通过构建一个Request对象来配置请求方式和请求参数,来发起网络请求的,所以Retrofit 也需要一个构建 Request 对象的过程,这个过程就隐藏在 RequestFactory 中。
RequestFactory采用了建造者模式,其 create(Object[] args)方法就会根据各项解析结果,最终返回一个 okhttp3.Request 对象:
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
private final Method method;
private final HttpUrl baseUrl;
final String httpMethod;
private final @Nullable String relativeUrl;
private final @Nullable Headers headers;
private final @Nullable MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
final boolean isKotlinSuspendFunction;
okhttp3.Request create(Object[] args) throws IOException {
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args.length;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException(
"Argument count ("
+ argumentCount
+ ") doesn't match expected count ("
+ handlers.length
+ ")");
}
RequestBuilder requestBuilder =
new RequestBuilder(
httpMethod,
baseUrl,
relativeUrl,
headers,
contentType,
hasBody,
isFormEncoded,
isMultipart);
if (isKotlinSuspendFunction) {
// The Continuation is the last parameter and the handlers array contains null at that index.
argumentCount--;
}
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
argumentList.add(args[p]);
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.get().tag(Invocation.class, new Invocation(method, argumentList)).build();
}
}OkHttpCall 是实际上发起网络请求的地方,所以最终 RequestFactory 的 create 方法会由 OkHttpCall 的 createRawCall() 方法来调用:
final class OkHttpCall<T> implements Call<T> {
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;
}
}ResponseBody映射为UserBean
OkHttp 默认的接口返回值对象是 ResponseBody,如果不引入converter-gson,我们只能将接口请求结果都定义为 ResponseBody,而不能是具体的 Bean 对象,因为 Retrofit 无法自动地完成 ResponseBody 到 UserBean 之间的转换操作,需要我们将这种转换规则告知 Retrofit。而这个规则也就是Converter接口,对应它的 responseBodyConverter方法:
//TODO
