Retrofit 工作过程分析
简介
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的实际工作由 OkHttp 完成,而 Retrofit 负责网络请求接口的封装。当通过 Retrofit 进行网络请求时,实际上是使用 Retrofit 接口封装请求参数(如 Header、Url 等),然后由 OkHttp 完成请求操作。在服务器返回数据后,OkHttp 将原始结果交给 Retrofit,Retrofit 根据用户需求对结果进行解析。
1. Retrofit 的基本结构
理解 Retrofit 的基本结构有助于理解其工作原理:
- Retrofit:核心类,用于配置和创建网络请求。
- Call Adapter:将 Retrofit 的
Call对象转换为其他类型,例如 RxJava 的Observable。 - Converter:用于序列化和反序列化 HTTP 请求和响应的对象。
- ServiceMethod:表示一个接口方法的详细信息,包括 HTTP 请求的方法、URL、参数等。
- OkHttpCall:实现了 Retrofit 的 Call 接口,使用 OkHttp 发送实际的网络请求。
2. 创建 Retrofit 实例
代码示例
使用 Retrofit.Builder 创建 Retrofit 实例:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient())
.build();
Retrofit.Builder 源码分析
Retrofit.Builder 是一个静态内部类,用于构建 Retrofit 实例。它允许设置基础 URL、Converter、Call Adapter 和 OkHttpClient 等。
public static final class Builder {
private Platform platform; // 平台实例,用于获取当前平台的特定功能
private okhttp3.Call.Factory callFactory; // OkHttp 的调用工厂,用于创建网络调用。OkHttpClient实现了Factory接口
private HttpUrl baseUrl; // 基础 URL
private List<Converter.Factory> converterFactories = new ArrayList<>(); // 数据转换器工厂集合
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>(); // 调用适配器工厂集合
public Builder() {
// 使用 Platform.get() 获取当前平台的实例,以便在不同平台上执行不同的逻辑
this(Platform.get());
}
public Builder callFactory(okhttp3.Call.Factory factory) {
// 设置 OkHttp 的调用工厂
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
public Builder baseUrl(HttpUrl baseUrl) {
// 设置基础 URL
this.baseUrl = checkNotNull(baseUrl, "baseUrl == null");
return this;
}
public Builder addConverterFactory(Converter.Factory factory) {
// 添加数据转换器工厂
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
// 添加调用适配器工厂
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder callbackExecutor(Executor executor) {
// 设置回调执行器,用于在指定的线程中执行回调
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
public Retrofit build() {
// 检查基础 URL 是否为空,如果为空则抛出异常
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 如果没有设置自定义的调用工厂(OkHttpClient),则使用默认的 OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 如果没有设置自定义的回调执行器,使用平台默认的回调执行器
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 复制当前的调用适配器工厂列表,并添加平台默认的调用适配器工厂
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.adapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 复制当前的转换器工厂列表
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
// 创建并返回一个新的 Retrofit 实例
return new Retrofit(callFactory, baseUrl, converterFactories, callAdapterFactories, callbackExecutor, validateEagerly);
}
}
3. 创建接口的动态代理实现
代码示例
定义一个接口来描述 HTTP API:
public interface ApiService {
@GET("users/{user}")
Call<User> getUser(@Path("user") String userId);
}
通过 Retrofit 实例创建接口的实现:
ApiService apiService = retrofit.create(ApiService.class);
源码分析
在 Retrofit 中,通过 Retrofit#create 方法可以创建接口的动态代理实现,使得接口方法的调用能够被拦截并进入指定的处理逻辑。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
// 创建 ServiceMethod 对象,通过ServiceMethod解析方法注解及方法参数
ServiceMethod serviceMethod = loadServiceMethod(method);
// 创建 OkHttpCall 实例来处理 HTTP 请求
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 接收一个 `okHttpCall` 对象作为参数,并返回 Call 对象
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
- Proxy.newProxyInstance() 方法: 创建动态代理对象,需要指定类加载器、实现的接口数组和
InvocationHandler对象,用于处理方法调用。 - InvocationHandler.invoke() 方法: 当代理实例上的方法被调用时执行,负责拦截方法调用并进行相应处理。
4. 创建 Call 对象
代码示例
Call<User> call = apiService.getUser("exampleUser");
源码分析
当调用 apiService.getUser 方法后,会执行动态代理类中的 invoke 方法。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
// 创建 ServiceMethod 对象,通过ServiceMethod解析方法注解及方法参数
ServiceMethod serviceMethod = loadServiceMethod(method);
// 创建 OkHttpCall 实例来处理 HTTP 请求
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 接收一个 `okHttpCall` 对象作为参数,并返回 Call 对象
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
- ServiceMethod 对象创建: 通过
loadServiceMethod()方法解析方法的注解,创建包含 HTTP 请求详细信息的ServiceMethod对象。 - OkHttpCall 对象创建: 使用
ServiceMethod对象和方法参数创建OkHttpCall实例,用于执行 HTTP 请求。 - CallAdapter 对象创建: 在
ServiceMethod的build方法中创建CallAdapter对象,用于将OkHttpCall适配为接口方法的返回类型。 - callAdapter.adapt(okHttpCall): 它接收一个
okHttpCall对象作为参数,并返回 Call 对象。代码示例中的Call<User> call就是通过callAdapter.adapt(okHttpCall)方法返回的。
如果不设置自定义的 CallAdapterFactory,Retrofit 默认使用 ExecutorCallAdapterFactory。ExecutorCallAdapterFactory 源码如下:
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
}
从上面代码可以看到,callAdapter.adapt(okHttpCall) 方法返回的是 ExecutorCallbackCall 对象。
5. 发起请求
代码示例
调用接口方法发起网络请求:
// Call<User> call = apiService.getUser("exampleUser");
call.enqueue(new Callback<User>() {
@Override
public void onResponse(Call<User> call, Response<User> response) {
// Handle response
}
@Override
public void onFailure(Call<User> call, Throwable t) {
// Handle failure
}
});
源码分析
在分析 Call 对象创建过程时,可以发现 callAdapter.adapt(okHttpCall) 方法返回的是 ExecutorCallbackCall 对象,因此 call.enqueue(new Callback<User>() {}) 方法最终调用的也是 ExecutorCallbackCall 对象的 enqueue 方法。
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) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
// ...
}
@Override
public void onFailure(Call<T> call, final Throwable t) {
// ...
}
});
}
}
在 ExecutorCallbackCall 的 enqueue 方法中,调用了 delegate.enqueue(new Callback<T>() {}),其中 delegate 就是传递进来的 OkHttpCall 对象。
OkHttpCall 类实现了 Call 接口,使用 OkHttp 发送实际的网络请求:
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T> serviceMethod;
private final Object[] args;
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
@Override
public void enqueue(Callback<T> callback) {
// 使用 OkHttp 发送异步请求
}
}
总结
Retrofit 的工作过程可以概括为以下几个步骤:
- 创建 Retrofit 实例: 使用
Retrofit.Builder配置基础 URL、Converter、Call Adapter 和 OkHttpClient 等。 - 定义接口并创建动态代理实现: 定义描述 HTTP API 的接口,并通过
Retrofit#create方法创建接口的动态代理实现。 - 创建 Call 对象: 调用接口方法时,通过动态代理创建
ServiceMethod和OkHttpCall对象,并使用CallAdapter将OkHttpCall适配为接口方法的返回类型。 - 发起请求: 调用
Call对象的enqueue方法,实际由OkHttpCall使用 OkHttp 发送异步网络请求。
通过动态代理和注解处理,Retrofit 极大地简化了网络请求的编写和维护。