关于 Retorfit

Retrofit 是如何工作的?

疑惑

  • 调用接口的方法后是怎么发送请求的?
  • Retrofit 与 OkHttp 是怎么合作的?
  • Retrofit 中的数据究竟是怎么处理的?它是怎么返回 Rxjava.Observable 的?

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface ApiService{
@GET("data/Android/" + GankConfig.PAGE_COUNT + "/{page}")
Observable<GankResponse> getAndroid(@Path("page") int page);
}

// Builder 模式来构建 retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baskUrl)
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(okHttpClient)
.build();
// 通过 retrofit.create 方法来生成 service
ApiService service = retrofit.create(ApiService.class);
// 发起请求获取数据
Observable<GankResponse> observable = service.getAndroid(1);
observable...

build()方法分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    /**
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
// Builder 模式创建 retrofit 实例
public Retrofit build() {
if (baseUrl == null) { // 检查 baseUrl 是否存在
throw new IllegalStateException("Base URL required.");
}

okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) { // 默认创建并使用 OkHttpClient
callFactory = new OkHttpClient();
}

Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) { // 若无设置则默认获取的是能运行在主线程的 Executor
callbackExecutor = platform.defaultCallbackExecutor();
}

// Make a defensive copy of the adapters and add the default Call adapter.
= List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}

Retrofit.create()方法分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service); // 验证接口是否合理
if (validateEagerly) { // 默认 false
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
// 平台的抽象,指定默认的 CallbackExecutor,CallAdapterFactory 用,这里 Android 平台 是 Android
private final Platform platform = Platform.get();
// ApiService 中的方法调用都会走到这里
@Override public Object invoke(Object proxy, Method method, 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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 为 Method 生成一个 ServiceMethod
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 再包装成 OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); // 请求
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}

从上面的代码中可以看到,Retrofit 主要原理是利用了 Java 的动态代理技术,把 ApiService 的方法调用集中到了InvocationHandler.invoke(),再创建了 ServiceMethod,OkHttpCall,返回callAdapter.adapt的结果。

ServiceMethod 的职责以及 loadServiceMethod 分析

ServiceMethod 是接口具体方法的抽象,它主要负责解析它对应的 method 的各个参数(它有各种如parseHeader()的方法),比如注解@GET,入参,另外还负责获取 callAdapter,responseConverter 等 Retrofit 配置,好为后面的 okhttp3.Request 做好参数准备,它的toRequest()为 OkHttp 提供 Request,可以说它承载了后续 Http 请求所需的一切参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method); //ConcurrentHashMap
if (result != null) return result;

synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// 缓存中没有,构建缓存并存储
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}

动态代理是有一定的性能损耗的,并且 ServiceMethod 的创建伴随着各种注解参数解析,这也是耗时间的,再加上一个 App 调用接口是非常频繁的,如果每次接口请求都需要重新生成那么有浪费资源损耗性能的可能,所以这里做了一份缓存来提高效率。

OkHttpCall

OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);是在为 ServiceMethod 以及 args 生成了一个 OkHttpCall。从 OkHttpCall 这个名字可以猜到,它是对 OkHttp3.Call 的组合包装。(OkHttpCall 中有一个成员okhttp3.Call rawCall)。

callAdapter.adapt()流程分析

最后return serviceMethod.callAdapter.adapt(okHttpCall);这里涉及到的callAdapter是由我们配置 Retrofit 时addCallAdapterFactory()方法中传入的如RxJavaCallAdapterFactory.create()生成,实例为RxJavaCallAdapterFactory

实例生成的大致流程:

ServiceMethod.Builder.build() -> ServiceMethod.createCallAdapter() -> retrofit.callAdapter() -> adapterFactories遍历 -> 最终到RxJavaCallAdapterFactory.get()#getCallAdapter() -> return new SimpleCallAdapter(observableType, scheduler);

这里使用的是 RxJava,最终得到的是 callAdapter 为 SimpleCallAdapter,所以接下来分析SimpleCallAdapter#adapt()

1
2