一、简介
Retrofit 是一个基于并封装了 OkHttp 的 RESTful 网络请求框架,网络请求工作本质上由 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装。它使用注解配置网络请求参数,且框架内部使用了大量的设计模式,不仅简化了使用,也降低了模块间的耦合,提高了扩展性,支持 RxJava 框架和 Gson、Protobuf 等序列化格式,是一款功能十分强大的开源框架。
使用 Retrofit 框架进行网络请求的过程为:
- 请求过程:在应用内通过 Retrofit 发起一个网络请求,Retrofit 会将这个请求封装成一个 OkHttp 可执行的任务,交由 OkHttp 发送网络请求给服务器
- 返回过程:服务器返回响应数据,由 OkHttp 接收并交给 Retrofit,Retrofit 对响应数据进行格式转换,转换成应用要求的数据格式后返回给应用
上述过程中,Retrofit 内部会有一些专门的角色对请求或响应做专门的处理,下面来认识一下它们。
1.1 Retrofit 中的重要角色
1.2 异步执行流程图
图片来源:网络请求库Retrofit源码分析
Retrofit 是我们自己可以尝试写出来的框架,它除了 23 个注解外只有 17 个类,使用了 24 种常用设计模式中的 9 种。
下面会结合 Retrofit 的使用来看源码,使用的 Retrofit 是 2.9.0 版本。
1.3 重要接口介绍
1.3.1 Call
这个 Call 接口是 Retrofit 定义的 Call,用来控制任务的执行、取消、超时等工作,更像是任务执行器,它并不是 OkHttp 的 Call(OkHttp 的 Call 接口上没有定义泛型),不要混淆:
public interface Call<T> extends Cloneable {
/**
* 同步发送请求并返回其响应
*/
Response<T> execute() throws IOException;
/**
* 异步发送请求,当有响应或者是与服务器通信、创建请求或处理响应时发生错误
* 使用 callback 回调进行通知
*/
void enqueue(Callback<T> callback);
/**
* 如果这个 Call 对象已经被 execute() 执行或者通过 enqueue(Callback) 入队就
* 返回 true。一个 Call 只能被执行或入队一次
*/
boolean isExecuted();
/**
* 取消此调用。将尝试取消正在进行中的调用,如果调用尚未执行,则永远不会执行
*/
void cancel();
/** 如果调用了 cancel() 则返回 true*/
boolean isCanceled();
/**
* 创建一个与此调用相同的新调用,即使此调用已经被执行或入队,也可以对其进行入队或执行
*/
Call<T> clone();
/** 原始的HTTP请求 */
Request request();
/**
* 返回一个跨越整个调用的超时时间:解析DNS、连接、写入请求体、服务器处理和
* 读取响应体。如果调用需要重定向或重试,所有操作必须在一个超时时间内完成
*/
Timeout timeout();
}
Retrofit 为 Call 提供了两个实现类:
- OkHttpCall:封装了 OkHttp,使用 OkHttp 发送网络请求
- DefaultCallAdapterFactory.ExecutorCallbackCall:仅在使用默认的请求适配器 DefaultCallAdapter 时才会用到,它会接收两个成员
Call<T> delegate
和Executor callbackExecutor
,前者作为代理执行网络请求,后者则根据请求的执行结果进行相应的回调
1.3.2 CallAdapter
/**
* 将响应类型为 R 的 Call 适配成 T 类型。CallAdapter 的实例由安装在 Retrofit
* 实例中的工厂(指 CallAdapter.Factory 接口)来创建
*/
public interface CallAdapter<R, T> {
/**
* 返回该适配器在将 HTTP 响应体转换为 Java 对象时使用的值类型。例如,Call<Repo> 的
* 响应类型为 Repo,这个类型值用于准备将 Call 对象传递给 adapt()
*/
Type responseType();
/**
* 返回一个委托给 Call 对象的实例 T。比如说,给你一个 Async,调用 adapt() 后
* 返回的是 Async<R>,R 是 Call 的泛型类型。
*
* @Override
* public <R> Async<R> adapt(final Call<R> call) {
* return Async.create(new Callable<Response<R>>() {
* @Override
* public Response<R> call() throws Exception {
* return call.execute();
* }
* });
* }
*/
T adapt(Call<R> call);
/**
* 基于网络请求接口方法的返回值类型,创建 CallAdapter 实例
*/
abstract class Factory {
/**
* 为返回 returnType 类型的接口方法返回一个 CallAdapter,如果这个工厂处理不了则返回 null
*/
public abstract @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit);
/**
* 从 type 的第 index 位置上的泛型参数抽取出上限,例如
* Map<String, ? extends Runnable>,index 为 1 时会返回 Runnable
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
/**
* 从 type 中抽取原始类型,例如 type 表示 List<? extends Runnable> 就返回 List.class
*/
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
1.3.3 Converter
public interface Converter<F, T> {
@Nullable
T convert(F value) throws IOException;
/** 基于类型和目标的用途创建 Converter 实例的工厂 */
abstract class Factory {
/**
* 返回一个 Converter,用于将 HTTP 响应体转换为 type,如果该工厂无法
* 处理 type,则返回 null。该方法用于创建响应类型的转换器,如从
* Call<SimpleResponse> 的声明中创建 SimpleResponse
*/
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
* 返回一个 Converter,用于将 type 转换成 HTTP 请求体,如果该工厂无法
* 处理则返回 null。该方法用于根据 Body、Part、PartMap 的值创建类型转换器
*/
public @Nullable Converter<?, RequestBody> requestBodyConverter(
Type type,
Annotation[] parameterAnnotations,
Annotation[] methodAnnotations,
Retrofit retrofit) {
return null;
}
/**
* 返回一个 Converter,用于将 type 转换成 String,如果该工厂不能处理则返回
* null。这用于根据 Field 和 FieldMap 的值,以及 Header、HeaderMap、Path、
* Query、QueryMap 的值创建转换器
*/
public @Nullable Converter<?, String> stringConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
* Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
* example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
* 从 type 中提取 index 处泛型参数的上界,如 Map<String, ? extends Runnable>
* 的索引为 1 时提取出的是 Runnable
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
/**
* 从 type 中提取原始类类型。例如,List<? extends Runnable> 的类型返回 List.class
*/
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
二、Retrofit 对象创建
Retrofit 本身使用了外观模式,其网络请求功能是通过 OkHttp 实现的,但是 Retrofit 框架对外提供的所有功能都只需通过 Retrofit 对象便可获取。
Retrofit 使用构建者模式创建 Retrofit 对象:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://restapi.amap.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
Retrofit.Builder 配置的属性:
public static final class Builder {
// 区分平台的,Android 或其它支持 Java8 的平台
private final Platform platform;
// Retrofit 中默认的是 OkHttpClient
private @Nullable okhttp3.Call.Factory callFactory;
// 唯一必填项,其它属性如不配置可以使用框架内默认的
private @Nullable HttpUrl baseUrl;
/**
* 数据转换器工厂集合。数据转换器工厂会生成相应的数据转换器,而数据转换器会将某种类型的数据
* 转换成目标类型,如常用的 GsonConverterFactory 会生产出 GsonResponseBodyConverter,将
* Retrofit 默认的响应体 ResponseBody 转换成 Gson
*/
private final List<Converter.Factory> converterFactories = new ArrayList<>();
/**
* 请求适配器工厂集合。请求适配器工厂会生成相应的请求适配器,而请求适配器会将某种请求转换成
* 目标平台或架构可执行的请求类型,如常用的 RxJavaCallAdapterFactory 会生成 RxJavaCallAdapter,
* 将 Retrofit 默认的网络请求 Call 转换成 RxJava 可执行的 Observable
*/
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
// 回调执行器,默认是一个主线程 Handler
private @Nullable Executor callbackExecutor;
// 标志位,表示是否提前对业务接口中的注解进行验证转换
private boolean validateEagerly;
}
在 Builder.build() 时会对上述属性赋值:
/**
* 用给定的配置创建一个 Retrofit 实例,如果 client() 和 callFactory() 都没有被调用,
* 那么将创建并使用一个默认的 OkHttpClient
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 默认只支持 OkHttp 请求,不支持 HttpUrlConnection 和 HttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 回调执行器,异步任务有结果后通过回调通知调用方结果
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// platform 的 defaultCallbackExecutor() 返回空,而其子类 Android 的同名方法会返
// 回一个 MainThreadExecutor,其内部持有主线程的 Handler 并通过 post() 将任务切换
// 到主线程,这样就不用像 OkHttp 那样手动切换线程了
callbackExecutor = platform.defaultCallbackExecutor();
}
// 在 this.callAdapterFactories 的基础上创建一个请求适配器工厂,并添加平台默认的适配器工厂
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 创建数据转换器工厂集合,添加 BuiltInConverters、this.converterFactories 以及
// 平台默认的数据转换器
List<Converter.Factory> converterFactories =
new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 先添加内置转换器 BuiltInConverters,这样可以防止覆盖其行为,
// 同时确保在使用消耗所有类型的转换器时保持正确的行为
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
在 build() 中我们能看到,除了 baseUrl 是必须配置的属性之外,其它的属性都是可选的,如果你不配置,在 build() 内会为这些属性配置默认值,如:
- callFactory 默认是 OkHttpClient
- callbackExecutor 默认值是 platform.defaultCallbackExecutor()
- callAdapterFactories 会在集合最后添加 platform.defaultCallAdapterFactories(callbackExecutor) 的所有成员
- converterFactories 会在集合最后添加 platform.defaultConverterFactories()
我们在介绍 Builder 属性时说过,Platform 是用来进行平台区分的,不同平台配置的默认 callbackExecutor、CallAdapterFactory、ConverterFactory 是不同的,下面还是简单了解下 Platform。
2.1 Platform
当前 Retrofit 版本将 Platform 分成两类:Android 与其它(支持 Java8 的平台)。我们先来看 Platform 的初始化,在 Retrofit.Builder 的构造方法中:
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
如果你没有指定 Platform 对象,默认会采用 Platform.get() 的返回值给 platform 赋值,而 Platform.get() 最终指向 Platform 的 findPlatform():
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
// 根据系统属性判断是 Android 平台还是其它平台
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android()
: new Platform(true); // hasJava8Types 直接赋值为 true
}
}
}
如果 “java.vm.name” 的值为 “Dalvik” 说明是在 Android 平台上运行,findPlatform() 会返回 Platform 的子类 Android,该类的主要内容如下:
static final class Android extends Platform {
Android() {
// SDK≥24 时 hasJava8Types 为 true
super(Build.VERSION.SDK_INT >= 24);
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
// 持有主线程的 Handler,并且 execute() 会将任务 post() 到主线程
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
Android 平台默认的回调执行器是 MainThreadExecutor,本质上是一个主线程的 Handler,通过这个 MainThreadExecutor 执行的任务都会被 Handler post() 到主线程。
回过头看 Platform 中的剩余内容:
// 是否支持 Java8
private final boolean hasJava8Types;
private final @Nullable Constructor<Lookup> lookupConstructor;
// hasJava8Types 为 true 时 lookupConstructor 才有值,否则为 null
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
Constructor<Lookup> lookupConstructor = null;
if (hasJava8Types) {
// lookupConstructor 赋值过程,省略了...
}
// hasJava8Types 如果为 false 那 lookupConstructor = null
this.lookupConstructor = lookupConstructor;
}
@Nullable
Executor defaultCallbackExecutor() {
return null;
}
// 如果 hasJava8Types 为 true,那么返回的 List 中包含两个 CallAdapter.Factory,
// 分别是 CompletableFutureCallAdapterFactory 和 DefaultCallAdapterFactory
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
// 如果 hasJava8Types 为 true,那么返回的 List 中有一个 OptionalConverterFactory,
// 否则返回一个空集合
List<? extends Converter.Factory> defaultConverterFactories() {
return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
}
@IgnoreJRERequirement
// Only called on API 24+.
boolean isDefaultMethod(Method method) {
return hasJava8Types && method.isDefault();
}
所以,整体看下来,Platform 内几个 default 开头的方法,为 Retrofit.Builder 设置了:
- defaultCallbackExecutor():Platform 会返回 null,而子类 Android 会返回一个 MainThreadExecutor,帮助我们将 Runnable 任务放到主线程中执行,从而实现了线程切换
- defaultCallAdapterFactories():如果 Platform 内的 hasJava8Types 为 true,返回的请求适配器工厂集合包含 CompletableFutureCallAdapterFactory 和 DefaultCallAdapterFactory,否则只包含 DefaultCallAdapterFactory
- defaultConverterFactories():如果 Platform 内的 hasJava8Types 为 true,返回的数据转换器工厂集合包含 OptionalConverterFactory,否则返回空集合
2.2 总结
Retrofit 框架通过构建者模式创建 Retrofit 对象时,主要是配置了如下属性:
- baseUrl:网络请求地址,是唯一必须配置的属性
- callFactory:OkHttp3 中的网络请求工厂,在 Retrofit 中默认为 OkHttpClient。这是 Retrofit 封装 OkHttp 的一个核心表现
- callbackExecutor:网络请求回调执行器,默认情况下,Android 平台会返回 MainThreadExecutor,在异步任务响应结果时,将回调放在 post() 内执行,避免手动切换到主线程
- callAdapterFactories:网络请求转换器工厂 CallAdapter.Factory 的集合,默认值放在集合的最后。集合内的适配器工厂会把 OkHttp 的 Call 转换成目标任务,比如支持 RxJava 的适配器工厂 RxJavaAdapterFactory 会将 Call 转换成 Observable
- converterFactories:数据转换器工厂,默认值放在集合的最后。转换器会将返回的数据流转换成需要的格式,如 GsonConverterFactory 就会把数据转换成 Gson 格式的
三、创建接口对象
创建完 Retrofit 对象,下一步就该创建网络请求的接口对象了。如下 WeatherService 是网络请求接口,内部定义了网络请求方法:
public interface WeatherService {
/**
* post 请求获取天气信息,相对 url 是 /v3/weather/weatherInfo
*/
@POST("/v3/weather/weatherInfo")
@FormUrlEncoded
Call<ResponseBody> postWeather(@Field("city") String city, @Field("key") String key);
/**
* get 请求获取天气信息,相对 url 是 /v3/weather/weatherInfo
*/
@GET("/v3/weather/weatherInfo")
Call<ResponseBody> getWeather(@Query("city") String city, @Query("key") String key);
}
使用时要通过 Retrofit.create() 创建这个接口对象:
WeatherApi weatherApi = retrofit.create(WeatherApi.class);
create() 实际上是为 XxxService 创建了一个动态代理对象,这样做的目的让该接口的所有方法,在被调用时都会先经过 InvocationHandler.invoke(),动态生成网络请求:
/**
* 1.创建网络请求实例
* 2.配置网络请求参数
*/
public <T> T create(final Class<T> service) {
// 1.验证服务接口
validateServiceInterface(service);
// 2.创建并返回 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 {
// 如果 method 是 Object 中定义的方法,那就走正常的调用流程
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
// 如果是接口内的默认方法,则执行默认方法调用,普通方法则执行
// method 对应的 ServiceMethod 的调用
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
3.1 验证网络请求接口
对接口及其方法进行验证:
private void validateServiceInterface(Class<?> service) {
// 1.如果 service 不是接口,则验证失败
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
Deque<Class<?>> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class<?> candidate = check.removeFirst();
// 2.如果接口上定义了泛型,则验证失败
if (candidate.getTypeParameters().length != 0) {
StringBuilder message =
new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
if (candidate != service) {
message.append(" which is an interface of ").append(service.getName());
}
throw new IllegalArgumentException(message.toString());
}
// 如果接口内部定义了其它接口,也要添加到 check 集合中进行检查
Collections.addAll(check, candidate.getInterfaces());
}
if (validateEagerly) {
Platform platform = Platform.get();
// 遍历服务接口内定义的所有方法
for (Method method : service.getDeclaredMethods()) {
// 如果不是默认方法和静态方法,就加载 method 对应的 ServiceMethod
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
}
validateServiceInterface() 主要做了两件事:
- 保证 service 必须是接口,并且 service 及其内部定义的接口类上都不能使用泛型
- 如果 validateEagerly 为 true,那么遍历 service 内所有的非默认、非静态方法,通过 loadServiceMethod(method) 找到/生成 method 对应的 ServiceMethod 对象
loadServiceMethod() 是一个非常重要的方法,它会先去缓存中查找 method 对应的 ServiceMethod 对象是否存在,如不存在,则解析方法及其参数上的注解生成一个 ServiceMethod 放进缓存中。在 validateEagerly 为 true 时调用 loadServiceMethod(),可能是为了保证 method 对应的 ServiceMethod 都在缓存中,从而减少后续在 InvocationHandler.invoke() 内调用 loadServiceMethod() 时所占用的时间。
3.2 为网络请求接口创建动态代理
回头看 create() 方法的返回值部分,直接 return 了一个 service 的动态代理对象,也就是说 service 所表示的网络请求接口内的所有方法,在被调用时,会先执行 InvocationHandler.invoke():
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 {
// 如果 method 是 Object 中定义的方法,那就走正常的调用流程
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
// method 如果是接口内的默认方法,则执行默认方法调用;如果是普通接口方法
// 则执行 method 对应的 ServiceMethod 的 invoke()
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
}
invoke() 会对网络请求接口内的默认方法和普通方法都进行处理,如果是默认方法那就执行默认方法的调用,如果是一个普通的接口方法,就通过 loadServiceMethod() 获取其对应的 ServiceMethod,并执行 ServiceMethod 的 invoke()。
四、执行接口方法
执行网络请求接口方法,得到一个 Retrofit.Call 的实例:
// 调用接口内方法获取到 Call 对象,通过异步请求将 Call 入队
Call<ResponseBody> call = weatherService.getWeather("Shenzhen", "key");
由于 weatherService 是一个动态代理对象,因此调用它的所有方法都会先执行 InvocationHandler.invoke(),进而执行 loadServiceMethod(method).invoke(args),下面来看这个过程。
4.1 loadServiceMethod()
loadServiceMethod() 会先去缓存 serviceMethodCache 中找 method 对应的 ServiceMethod 对象是否被缓存过,如果缓存命中则则取出缓存对象并返回,否则就去解析 method 上的注解,生成一个 ServiceMethod 对象,放入缓存并返回:
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) {
// 缓存未命中,解析方法及其参数上的注解,生成一个 ServiceMethod
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
4.2 生成 ServiceMethod
ServiceMethod 是对接口中网络请求方法的描述。在 Retrofit 2.9.0 版本中,ServiceMethod 已经被抽取为一个抽象类,它本身不再做过多的逻辑处理,这样做是为了更好地扩展和解耦。
首先我们对 ServiceMethod 有个宏观了解,它的继承体系如下:
大致的处理过程是:
- ServiceMethod 先将接口方法交给 RequestFactory,由 RequestFactory 解析方法以及方法参数上的注解,将相关信息保存在新建的 RequestFactory 对象中并返回
- ServiceMethod 将接口方法和 RequestFactory 交给 HttpServiceMethod,生成 callAdapter 和 responseConverter,再从 Retrofit 对象中取出 callFactory,用来创建 HttpServiceMethod 的具体子类
- HttpServiceMethod 的子类会实现 adapt(),内部实际上就是将适配任务交给 callAdapter,调用 callAdapter 的 adapt(),这一步也是 ServiceMethod 的核心功能
ServiceMethod 的全部代码如下:
abstract class ServiceMethod<T> {
// 通过解析方法上的注解,生成并返回一个进行网络请求的 ServiceMethod
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 1.解析注解得到一个 RequestFactory 用来生成网络请求
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 2.获取 method 带有泛型的返回值类型
Type returnType = method.getGenericReturnType();
// 2.1 返回值包含不能处理的泛型类型
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
// 2.2 返回值类型不能为 Void
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
// 3.解析注解生成 HttpServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
// 会通过请求适配器 CallAdapter 的 adapt() 将请求转换成目标格式
abstract @Nullable T invoke(Object[] args);
}
4.2.1 生成 RequestFactory
这里我们有必要先将 Retrofit 的接口方法使用示例再拿出来:
public interface WeatherService {
@POST("/v3/weather/weatherInfo")
@FormUrlEncoded
Call<ResponseBody> postWeather(@Field("city") String city, @Field("key") String key);
@GET("/v3/weather/weatherInfo")
Call<ResponseBody> getWeather(@Query("city") String city, @Query("key") String key);
}
我们看到方法上的注解标记了请求方式(GET、POST等)以及请求的相对 url(通常会与 baseUrl 拼接成完整的 url),而方法参数注解则会将相应信息存入请求体(@Body、@Path 注解等等),RequestFactory 正是要把这些注解信息解析出来,并在验证无误后保存。
parseAnnotations() 利用构造者模式先保存了 method 及其注解总体信息:
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
static final class Builder {
final Retrofit retrofit;
// 被解析的方法
final Method method;
// 方法上的所有注解
final Annotation[] methodAnnotations;
// 方法参数注解
final Annotation[][] parameterAnnotationsArray;
// 方法上所有泛型参数的类型
final Type[] parameterTypes;
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
}
}
然后在 build() 时会解析 method 上的注解内容,并保存:
RequestFactory build() {
// 遍历方法上的注解并解析保存注解信息
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 对解析结果进行验证...
// 遍历参数上的注解,将每个注解的具体类型转换成 ParameterHandler 的对应子类,
// 然后赋值到 parameterHandlers 数组的对应位置上
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
// 对参数解析结果进行验证...
return new RequestFactory(this);
}
build() 主要做两件事:
- 解析方法上的注解并保存相关属性,然后验证这些注解配置的正确性
- 解析方法参数上的注解,并将相关信息封装到 ParameterHandler 的具体子类中,也验证这些注解的正确性
解析方法注解
parseMethodAnnotation() 解析方法上的注解,以确定使用 Http 的哪一种请求方式和请求的相对地址:
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
parseHttpMethodAndPath():
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
// httpMethod 只允许赋值一次
if (this.httpMethod != null) {
throw methodError(
method,
"Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod,
httpMethod);
}
// 保存 httpMethod 和 hasBody
this.httpMethod = httpMethod;
this.hasBody = hasBody;
// 如果请求方式的注解值,即请求的相对 url 为空则不继续处理
if (value.isEmpty()) {
return;
}
// 如果请求中有查询参数,那么从 url 中找出这些查询参数
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(
method,
"URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.",
queryParams);
}
}
// 保存相对 url 和查询参数名字
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
方法上的注解解析,主要是确定了使用哪一个 Http 请求方法、是否有方法体、请求的相对地址、请求参数等信息。
解析方法参数注解
方法参数上可以使用的注解,与 ParameterHandler 内定义的子类是相对应的:
parseParameter() 就是要解析出参数使用的注解类型,生成 ParameterHandler 的对应子类,验证结果无误后返回:
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction =
// 解析所有可用在参数上的注解,有 500 多行代码...
parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
...
result = annotationAction;
}
}
// 对解析结果为空时的处理,省略...
return result;
}
parseParameterAnnotation() 是真正对所有参数注解进行解析的方法,会对上图中所有 ParameterHandler 内部类锁表示的注解进行解析,所以内容非常多,有 500 多行代码,这里我们就挑一个 @Body 说明一下:
@Nullable
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) {
...
} else if (annotation instanceof Path) {
...
} ... else if (annotation instanceof Body) {
validateResolvableType(p, type);
// @Body 注解不能用在 isFormEncoded、isMultipart 情况下
if (isFormEncoded || isMultipart) {
throw parameterError(
method, p, "@Body parameters cannot be used with form or multi-part encoding.");
}
// @Body 注解在参数中只能被使用一次
if (gotBody) {
throw parameterError(method, p, "Multiple @Body method annotations found.");
}
// 请求体的数据转换器
Converter<?, RequestBody> converter;
try {
converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
} catch (RuntimeException e) {
// Wide exception range because factories are user code.
throw parameterError(method, e, p, "Unable to create @Body converter for %s", type);
}
gotBody = true;
// 创建返回一个 ParameterHandler.Body 对象
return new ParameterHandler.Body<>(method, p, converter);
} else if (annotation instanceof Tag) {
...
}
return null; // Not a Retrofit annotation.
}
解析 @Body 注解的主要工作还算比较简单:
- 利用之前解析时生成的标记位做一些安全检查,规避使用者对当前注解的使用错误
- 生成一个请求体转换器,当然其它注解也可能会用到转换器,而且不一定就是请求体转换器,也可能是字符串转换器等等
- 创建返回一个 ParameterHandler.Body 对象。解析的是 XXX 注解,就会返回 ParameterHandler.XXX 对象
到这里,RequestFactory 对象创建工作就基本完成了,我们总结一下主要步骤:
- 先来到 RequestFactory.Builder 中,解析方法注解,保存 httpMethod、hasBody、relativeUrl 等成员
- 解析方法参数注解,将每个注解的信息封装在 ParameterHandler.XXX 子类中,XXX 为注解名称。所有的参数注解会封装在 ParameterHandler<?>[] parameterHandlers 成员中
- 最后通过构建者模式将 RequestFactory.Builder 中的成员属性传给 RequestFactory 对象保存
RequestFactory 是生产 okhttp3.Request 的工厂,目前仅是创建了这个工厂对象,还没有开始生产 Request,ParameterHandler 也是类似的情况,还没开始执行自身任务。
4.2.2 生成 HttpServiceMethod
HttpServiceMethod 的三个内部子类 CallAdapted、SuspendForResponse 和 SuspendForBody,后两个是 Kotlin suspend 函数相关,由于篇幅受限暂且略过,那么可以简单的认为 HttpServiceMethod 返回一个 CallAdapted:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
// 是否是 Kotlin 中被 Suspend 修饰的方法
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
// Kotlin 相关,省略...
} else {
// 方法上带有泛型的返回值作为适配器类型
adapterType = method.getGenericReturnType();
}
// 1.从 Retrofit 的 callAdapterFactories 集合中找到一个可以处理
// adapterType 类型的 CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
// responseType 及其它健壮代码,省略先..
// 2.从 Retrofit 的 converterFactories 集合中找到一个可以处理
// responseType 类型的 Converter
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
// 3.返回一个 HttpServiceMethod 的子类对象 CallAdapted
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} ...
}
生成 CallAdapted 需要拿到 callAdapter、responseConverter、callFactory 和前面已经生成的 requestFactory,callAdapter 和 responseConverter 实际上就是去 Retrofit 对象的适配器工厂集合 callAdapterFactories 和转换器工厂集合 converterFactories 中找合适的适配器和转换器。
生成 callAdapter
通过 createCallAdapter() 如何获取到一个 CallAdapter 对象?主要有两点:
- 通过我们在配置 Retrofit 时添加的适配器工厂获取
- 适配器工厂根据接口方法的返回值类型确定该工厂能否生成满足条件的 CallAdapter
下面看详细代码:
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
// callAdapter() 的返回值原本是 CallAdapter<?, ?>,但是被转换成了
// CallAdapter<ResponseT, ReturnT>
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
去 Retrofit 的 callAdapterFactories 集合中,找到一个能处理给定的 returnType 和 annotations 的适配器工厂:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
/**
* skipPast 表示遍历 callAdapterFactories 集合时会跳过哪些工厂
*/
public CallAdapter<?, ?> nextCallAdapter(
@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
...
// 由于 callAdapter() 传的是 null,表示不跳过工厂,那么 start 从 0 开始
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
// 在给定的范围内调用 CallAdapter.Factory.get() 获取一个 CallAdapter,如果
// 被遍历到的工厂不能生产出 returnType、annotations 的 CallAdapter 就返回 null
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
/**
* 如果没找到一个符合条件的 CallAdapter 对象,则会生成错误信息,包括跳过了哪些
* 工厂、从哪些工厂去找 CallAdapter,最后抛出带有这些信息的异常,省略这些代码...
*/
}
一个适配器工厂能不能生产出 CallAdapter,取决于 CallAdapter.Factory 接口的 get() 能否处理参数的 returnType、annotations,以默认的 DefaultCallAdapterFactory 为例:
/**
* 获取由 DefaultCallAdapterFactory 创建的 CallAdapter
*/
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
// returnType 的原始类型必须为 Call
if (getRawType(returnType) != Call.class) {
return null;
}
// returnType 必须带泛型,如 Call<Foo> 或 Call<? extends Foo>
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
// responseType 取 returnType 泛型的上限
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
/**
* 如果 annotations 中没有 SkipCallbackExecutor 注解,会取到 callbackExecutor,
* 回溯代码 callbackExecutor 是在 Retrofit.Builder 的 build() 中被
* platform.defaultCallbackExecutor() 赋值的,Platform 为 null,Android 为
* MainThreadExecutor
*/
final Executor executor =
Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
// 返回 CallAdapter 接口的匿名实现对象
return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
// 接收一个 Retrofit.Call,返回 ExecutorCallbackCall
@Override
public Call<Object> adapt(Call<Object> call) {
return executor == null ? call : new DefaultCallAdapterFactory.ExecutorCallbackCall<>(executor, call);
}
};
}
显然,对于 DefaultCallAdapterFactory 而言,只要给定的 returnType 是一个带有类型参数且原始类型为 Call,类似于 Call<Foo>
或者 Call<? extends Foo>
,就可以生成一个 CallAdapter 对象。只不过,如果参数 annotations 中没有 @SkipCallbackExecutor 注解,其 adapt() 就是接收一个 Call 适配出 DefaultCallAdapterFactory.ExecutorCallbackCall,否则就不进行适配,接收 call 返回的也是 call。
生成 responseConverter
与生成 CallAdapter 的过程非常类似,调用 createResponseConverter() 生成一个 Converter:
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 对象去寻找符合条件的 Converter 工厂:
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) {
...
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
// 遍历 converterFactories 并调用 Converter.Factory.responseBodyConverter()
// 看该转换器工厂能否处理以下 type 和 annotations,不能会返回 null
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
// 与前面的 nextCallAdapter() 一样,最后打印失败信息并抛出异常
}
这样就得到了一个 Converter 对象。
生成 HttpServiceMethod 子类对象
在获取了创建 HttpServiceMethod 子类对象所需的成员之后,就可以通过构造方法创建具体对象了。刨除掉 Kotlin 相关的两个子类 SuspendForResponse 和 SuspendForBody,大多数时候我们都会生成 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 将适配工作完全交给 CallAdapter 处理了。
4.3 调用 ServiceMethod 的 invoke()
回到 Retrofit 的 create(),现在已经通过 loadServiceMethod() 获取到接口方法对应的 ServiceMethod 对象了,最后还要调用其 invoke() 才能完成动态代理内的全部工作。HttpServiceMethod 是这样实现 invoke() 的:
@Override
final @Nullable ReturnT invoke(Object[] args) {
// HttpServiceMethod 中的 Call 默认是 OkHttpCall
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
可以看到 HttpServiceMethod 是默认使用了 OkHttpCall 作为 Retrofit.Call 的实现类的。这里 invoke() 并没有直接返回 OkHttpCall ,而是用 adapt() 又做了一步适配,将 OkHttpCall 转换成使用者需要的对象。比如说,你想通过 RxJava 发送请求,那么在配置 Retrofit 对象时就要向其添加请求适配器工厂 RxJava2CallAdapterFactory:
public static Retrofit getRetrofit() {
return new Retrofit.Builder()
.client(getOkHttpClient()) // 配置 OKHttpClient
.addConverterFactory(GsonConverterFactory.create()) // 添加 Json 解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 添加 RxJava
.build();
}
然后在执行 HttpServiceMethod.invoke() 时,会执行到具体子类的同名方法,以 CallAdapted 为例,就会直接调用 CallAdapter.adapt(),这个 CallAdapter 是在【4.2.2 的生成 callAdapter】这一节根据接口方法的返回值类型已经筛选出来,并在调用 CallAdapted 构造方法时传入了,所以它应该是 RxJava2CallAdapterFactory 生成的 RxJava2CallAdapter:
@Override public <R> Object adapt(Call<R> call) {
Observable<Response<R>> responseObservable = new CallObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
可以看到其 adapt() 传入了一个 Retrofit.Call 对象,返回一个 Observable 以进行 RxJava 的任务执行工作。
假如没有添加任何 CallAdapterFactory,并且接口方法的返回值类型就是 Call,那么就会取默认的 DefaultCallAdapterFactory 中那个匿名的 CallAdapter:
// 前面贴过一次了,这次就只贴部分需要使用的代码了
@Override
public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
...
// annotations 如果没有 SkipCallbackExecutor 注解,executor 就会取 callbackExecutor,
// 而 callbackExecutor 的默认取值为 platform.defaultCallbackExecutor(),对 Android
// 来说就是 MainThreadExecutor
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) {
// executor 不为空就会将 call 适配成 ExecutorCallbackCall
return executor == null ? call : new DefaultCallAdapterFactory.ExecutorCallbackCall<>(executor, call);
}
};
}
executor 不为空的情况下,adapt() 会返回一个 DefaultCallAdapterFactory.ExecutorCallbackCall 对象,在 Call 之上再封装一层,让 Call 作为代理去执行异步网络请求,同时用 callbackExecutor 做回调,把 Callback 的回调方法都通过 Handler.post() 放在主线程中执行,这样 Callback.onFailure() 和 Callback.onResponse() 也都会切换到主线程中:
/**
* 传递进来的 Call 作为 delegate 去真正的进行网络请求工作,而在异步执行产生结果时,
* 即在 onResponse() 和 onFailure() 内,通过 callbackExecutor 去执行 callback 回调。
* 换成具体例子,delegate 就是一个 OkHttpCall,callbackExecutor 就是 MainThreadExecutor,
* OkHttpCall 仍是具体执行网络请求的成员,而 MainThreadExecutor 会在需要执行 callback
* 回调时,切换到主线程
*/
static final class ExecutorCallbackCall<T> implements Call<T> {
// 默认是 MainThreadExecutor
final Executor callbackExecutor;
// 默认是 OkHttpCall
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override
public void enqueue(final Callback<T> callback) {
delegate.enqueue(
// 这是 OkHttp 的回调,由于是
new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(
// Runnable 通过 Handler 的 post() 被放入主线程执行
() -> {
if (delegate.isCanceled()) {
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();
}
}
因此 ServiceMethod.invoke() 会先得到一个 OkHttpCall,并根据 Retrofit 配置的转换器工厂和接口方法的返回值类型适配成合适的对象(比如 RxJava 的 Observable 或者默认的 ExecutorCallbackCall),以便做下一步的请求发送。
五、发送请求
最后就是发送请求了,默认 Retrofit 默认的异步方式就是调用 Call.enqueue(),完整请求如下:
private void request() {
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://restapi.amap.com").build();
// 获取到接口的动态代理对象
WeatherService weatherService = retrofit.create(WeatherService.class);
// 调用接口内方法获取到 Call 对象,通过异步请求将 Call 入队
Call<ResponseBody> call = weatherService.getWeather("Shenzhen", "key");
// 异步发送请求
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try (ResponseBody body = response.body()) {
String string = body.string();
Log.d(TAG, "onResponse: " + string);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
这个 call 的实际类型是 ExecutorCallbackCall,它的 enqueue() 会执行 delegate.enqueue(),而这个 delegate 默认是 OkHttpCall:
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
// 1.创建 OkHttp 的原始请求
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
// 失败回调
if (failure != null) {
callback.onFailure(this, failure);
return;
}
// 任务取消
if (canceled) {
call.cancel();
}
// 2.OkHttp 异步任务入队
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
// 3.解析 OkHttp 返回的 rawResponse
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
// 回调解析结果 response
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
...
});
}
在 parseResponse() 中解析原始响应:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
rawResponse =
rawResponse
.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
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);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
// 数据转换
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
catchingBody.throwIfCaught();
throw e;
}
}
responseConverter 也是在构造 HttpServiceMethod 时传入的,一般情况下为 Retrofit 配置的是 GsonConverterFactory,调用其 responseBodyConverter() 时会返回 GsonResponseBodyConverter,再调用其 convert() 将默认的 ResponseBody 转换为指定类型:
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
// 接收 ResponseBody 输出 T
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
如果没有为 Retrofit 添加任何数据转换器工厂,那么返回的就是默认的 ResponseBody(对 OkHttp Response 的封装)。