本文基于 Retrofit 2.5
Retrofit :改造
改造了什么呢?
把一个 Http 请求转化为一个 Java 接口的调用。
这是官网给的例子(http://square.github.io/retrofit/)。
定义 Service 接口,该接口内的方法就是 api 调用。
public interface GithubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
创建 Retrofit 对象,并通过 Retrofit 对象再创建 Service 接口实现类的对象。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GithubService githubService = retrofit.create(GithubService.class);
调用 Serice 对象的方法,发起网络请求。
Call<List<Repo>> repos = githubService.listRepos("gdeeer");
从这句开始。
Call<List<Repo>> repos = githubService.listRepos("gdeeer");
点进去,发现找不到 listRepos 的实现。因为 githubService 的类是动态生成的,我们看不到类的实现。
只能去看下生成 githubService 对象的代码。
GithubService githubService = retrofit.create(GithubService.class);
看 Retrofit 的 create() 方法。
public <T> T create(final Class<T> 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 {
...
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
可以看到,Retrofit 是通过 Proxy.newProxyInstance
来生成 GithubService 接口的实现类的,而接口内方法的处理逻辑就在 InvocationHandler 的 invoke() 中(更多关于Proxy.newProxyInstance
的内容可见Java 基础:静态代理和动态代理)。
invoke() 方法中执行了 loadServiceMethod(method).invoke(args)
。所以 githubService.listRepos("gdeeer");
方法的真正调用,就是在这里进行的。
看一下 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;
}
先从缓存中获取,缓存中没有,就通过 ServiceMethod.parseAnnotations()
来新建,并放入缓存。
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
...
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract T invoke(Object[] args);
}
ServiceMethod 是一个抽象类,只有一个方法 invoke(),ServiceMethod.parseAnnotations()
相当于一个工厂,用来创建 ServiceMethod 对象,它内部又调用了 HttpServiceMethod.parseAnnotations()
来创建。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
...
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
终于出现了 new HttpServiceMethod()
,HttpServiceMethod 是 ServiceMethod 的实现类,它接收4个参数:requestFactory、callFactory、callAdapter、responseConverter。
requestFactory
用来生成 okhttp3.Request,okhttp3.Request 代表一次 Http 请求。
callFactory
用来生成 okhttp3.Call,okhttp3.Call 代表一个准备好了的 Request。
callAdapter
用来处理 retrofit2.Call,retrofit2.Call 是 Retrofit 中定义的 Call,与 okhttp3.Call 基本一致,最终执行的还是 okhttp3.Call。
responseConverter
用来转化一个 response。
ServiceMethod.parseAnnotations() 方法中会创建 requestFactory。
// ServiceMethod.java
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
...
}
// RequestFactory.java
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
通过 RequestFactory.Builder 来创建一个 RequestFactory。
HttpServiceMethod 的 parseAnnotations() 方法中会创建 callFactory。
创建方式是直接使用 Retrofit 类的 callFactory。
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...) {
okhttp3.Call.Factory callFactory = retrofit.callFactory;
...
}
Retrofit 中的 callFactory 在 Retrofit.Builder.build()
时初始化。没有指定的话,默认就是一个 OkHttpClient
。
// Retrofit#Builder.java
public Retrofit build() {
...
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
...
}
HttpServiceMethod 的 parseAnnotations() 方法中会创建 callAdapter。
创建方式是通过 Retrofit 类,Retrofit 会遍历自己的 callAdapterFactories,找到合适的 CallAdaperFactory,如果找不到,会抛异常。
什么是合适的 CallAdaperFactory,就是能产生合适的 CallAdaper 的 Factory。什么是合适的 CallAdapter,就是能 Call 改编为指定的 returnType 的 CallAdapter。
CallAdapter
// HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...)(
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
...
}
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(...) {
...
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
...
}
// Retrofit.java
public CallAdapter<?, ?> callAdapter(...) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(...) {
...
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;
}
}
...
}
Retrofit 中的 callAdapterFactories 在 Retrofit.Builder.build()
时初始化。
// Retrofit#Builder.java
public Retrofit build() {
...
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
...
}
初始化时,根据所在的不同平台,会添加不同的默认工厂。
Android 平台上,callbackExecutor 是 MainThreadExecutor。若当前机器的 Android 版本号大于 24,会添加 CompletableFutureCallAdapterFactory、ExecutorCallAdapterFactory。若小于等于 24,只添加一个 ExecutorCallAdapterFactory。
Java8 平台上,callbackExecutor 是 null。会添加 CompletableFutureCallAdapterFactory、 DefaultCallAdapterFactory。
DefaultCallAdapterFactory 只能生产 DefaultCallAdapter,它将 Call 改编为 Call
(它自己)。
ExecutorCallAdapterFactory 只能生产 ExecutorCallAdapter,它将 Call 改编为 ExecutorCallbackCall
(也是一个 Call)。
CompletableFutureCallAdapterFactory 只能生产 CompletableFutureCallAdapter(实际上是 BodyCallAdapter、ResponseCallAdapter),它将 Call 改编为 CompletableFuture
。
HttpServiceMethod 的 parseAnnotations() 方法中会创建 callAdapter。
创建方式是通过 Retrofit 类,Retrofit 会遍历自己的 converterFactories,找到合适的 ConverterFactory,如果找不到,会抛异常。
什么是合适的 ConverterFactory,就是能生产合适的 Converter 的 Factory。什么是合适的 Converter,就是能将 ResponseBody 转化为指定 returnType 的 Converter。
Converter
// HttpServiceMethod.java
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(...) {
...
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
...
}
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(...) {
...
return retrofit.responseBodyConverter(responseType, annotations);
...
}
// Retrofit.java
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(...) {
...
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) {
return (Converter<ResponseBody, T>) converter;
}
}
...
}
Retrofit 中的 converterFactories 在 Retrofit.Builder.build()
时初始化。
// Retrofit#Builder.java
public Retrofit build() {
...
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
...
}
初始化时,根据所在的不同平台,会添加不同的默认工厂。
Android 平台上,只会添加 BuiltInConverters。
Java8 平台上,会添加 BuiltInConverters、OptionalConverterFactory。
BuiltInConverters:
@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
if (checkForKotlinUnit) {
try {
if (type == Unit.class) {
return UnitResponseBodyConverter.INSTANCE;
}
} catch (NoClassDefFoundError ignored) {
checkForKotlinUnit = false;
}
}
return null;
}
它只能生产可以将 ResponseBody 转化为:ResponseBody
、Void
、Unit
的 Converter,如果指定的 returnType 不是这几种,就会返回 null。
OptionalConverterFactory:
@Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(type) != Optional.class) {
return null;
}
Type innerType = getParameterUpperBound(0, (ParameterizedType) type);
Converter<ResponseBody, Object> delegate =
retrofit.responseBodyConverter(innerType, annotations);
return new OptionalConverter<>(delegate);
}
它只能生产 OptionalConverter,它将 ResponseBody 转化为 Optional
,如果指定的 returnType 不是 Optional,就会返回 null。
获取到 HttpServiceMethod 对象后,就会调用它的 invoke 方法。
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
里面通过 requestFactory、callFactory、responseConverter 生成了一个 OkHttpCall
对象,CallAdapter 处理的就是它。
OkHttpCall 是 Retrofit2.Call 的实现类,它会包含一个 okhttp3.Call 的对象 rawCall,rawCall 通过 callFactory、requestFactory 创建。
okhttp3.Call rawCall = callFactory.newCall(requestFactory.create(args));
接下来看 callAdapter 的 adapt() 方法。
adapt() 方法在 retrofit 包中,有四处实现。即包中定义了四个 CallAdapter,DefaultCallAdapter、ExecutorCallAdapter、BodyCallAdapter、ResponseCallAdapter。
DefaultCallAdapter
将 Call 改编为 Call。
ExecutorCallAdapter
将 Call 改编为 ExecutorCallbackCall(也是一个 Call)。
BodyCallAdapter
、ResponseCallAdapter
将 Call 改编为 CompletableFuture(Java8 中的类)。
我们再回头看下最开始的代码。
Call<List<Repo>> repos = githubService.listRepos("gdeeer");
实际运行后,发生了异常。
异常发生在 HttpServiceMethod.createResponseConverter() 方法中,即生产 Converter 的方法中。
如上面 2.1.1.4 中所说,生产 Converter 时,会遍历 Retrofit 中的 converterFactories,如果没有找到合适的 ConverterFactory,就会抛出异常。
默认的 converterFactories,只能生产 returnType 是 ResponseBody
、Void
、Unit
、Optional
的 converter。但我们的 listRepos() 方法的 returnType 是 Call
,所以它会返回 null。>
系统内置的 ConverterFactory 不满足需求,我们只能自己创建新的 ConverterFactory。
官方文档上说,Retrofit 默认只支持将 HTPP bodies 转为 ResponseBody。如果要支持其他类型,需要使用新的 Converter,并提供了几种 Converter 库。
我们使用 GsonConverter 来转化,引入 converter-gson 库后,修改 Retrofit 的 build 代码。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
现在代码就可以正常运行了。
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
RxJava2CallAdapter 将 Call 改编为一个 Observable。
Observable subscribe 时,会执行 Call,在 onNext 中回调。
上面的目录已经很清楚,总结一下就是:
应该是开发者觉得以后还有除了 HttpServiceMethod 以外的 ServiceMethod 实现类,但是他们都需要 requestFactory,所以放在调用 HttpServiceMethod.parseAnnotations 之前生成。
因为 CallAdatper、ResponseConverter 对于每个方法来说,不管调用几次,它们的值都不变,但对于 Request、Call 来说,每次调用,都要产生不同的对象。
实现 retrofit2.Call 接口的有两个类,一个是代理了 okhttp3.Call 的 OkHttpCall
类,另一个是代理了另一个 retrofit2.Call
的 ExecutorCallbackCall 类。
ExecutorCallbackCall 会把 retrofit2.Call 的 execute()、enqueue() 方法都放到 Executor 中执行。
RequestFactory 在 ServiceMethod.parseAnnotations
中生成。
Request 在 OkHttpCall.createRawCall 中生成并使用,用来生成 okhttp3.Call。
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;
}
CallFactory 在 Retrofit.Builder.build() 方法中生成(即 OkHttpClient)。
Call 在 OkHttpCall.createRawCall 中生成并使用,用来生成 okhttp3.Call(会委托 OkHttpCall 调用它的方法)。OkHttpCall.createRawCall 在 OkHttpCall 执行方法时调用。
OkHttpCall 在 HttpServiceMethod.invoke 方法中生成。用户调用 api 方法后,获得 CallAdapter.adapt 生成的对象,再调用该对象的方法时使用。
CallAdapterFactory 在 Retrofit.Builder.build() 方法中生成。
CallAdapter 在 ServiceMethod.parseAnnotations
中生成,在用户调用 api 方法时使用。
ConverterFactory 在 Retrofit.Builder.build() 方法中生成。
Converter 在 ServiceMethod.parseAnnotations
中生成,在 OkHttpCall.execute
、OkHttpCall.enqueue
时使用。