注:本文基于 Retrofit2.0版本,并配合 RxJava 来分析。
com.squareup.retrofit2:retrofit:2.0.0
com.squareup.retrofit2:converter-gson:2.0.0
com.squareup.retrofit2:adapter-rxjava:2.0.0
Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to how requests are made.
本文主要通过分析 Retrofit 与 RxJava 的合作流程 来深入理解 Retrofit的工作原理,并且解答自己心中的疑惑。
疑惑
- 我们调用接口的方法后是怎么发送请求的?这背后发生了什么?
- Retrofit 与 OkHttp 是怎么合作的?
- Retrofit 中的数据究竟是怎么处理的?它是怎么返回 RxJava.Observable 的?
Retrofit 的基本使用
1 | public interface ApiService{ |
Retrofit 就这样经过简单的配置后就可以向服务器请求数据了,超级简单。
Retrofit.create 方法分析
Retrofit的create方法作为 Retrofit 的入口,当然得第一个分析。
1 | public <T> T create(final Class<T> service) { |
在上面的代码中可以看到,Retrofit 的主要原理是利用了 Java 的动态代理技术,把 ApiService 的方法调用集中到了InvocationHandler.invoke,再构建了ServiceMethod ,OKHttpCall,返回 callAdapter.adapt 的结果。
要弄清楚,还需要分析那最后三行代码。
一步一步来。
ServiceMethod的职责以及 loadServiceMethod分析
我认为 ServiceMethod 是接口具体方法的抽象,它主要负责解析它对应的 method 的各种参数(它有各种如 parseHeaders 的方法),比如注解(@Get),入参,另外还负责获取 callAdapter,responseConverter等Retrofit配置,好为后面的okhttp3.Request做好参数准备,它的toRequest为 OkHttp 提供 Request,可以说它承载了后续 Http 请求所需的一切参数。
再分析loadServiceMethod,比较简单。
1 | // serviceMethodCache 的定义 |
loadServiceMethod方法,负责 为 method 生成一个 ServiceMethod ,并且给 ServiceMethod 做了缓存。
动态代理是有一定的性能损耗的,并且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.Bulider.Build()
->ServiceMethod.createCallAdapter()
->retrofit.callAdapter()
->adapterFactories遍历
->最终到RxJavaCallAdapterFactory.get()#getCallAdapter()
->return return new SimpleCallAdapter(observableType, scheduler);
由于使用了 RxJava ,我们最终得到的 callAdapter 为 SimpleCallAdapter,所以接下去分析SimpleCallAdapter的 adapt 方法:
这里涉及到的 CallOnSubscriber 后面有给出:
1 | public <R> Observable<R> adapt(Call<R> call) { |
1 | static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> { |
SimpleCallAdapter.adapt 很简单,创建一个 Observable获取CallOnSubscribe中的Response
1 | // OkHttpCall.execute |
经过一连串的处理,最终在 OkHttpCall.execute() 的方法中生成 okhttp3.call 交给 OkHttpClient 去发送请求,再由我们配置的 Converter(本文为GsonConverterFactory) 处理 Response,返回给SimpleCallAdapter处理,返回我们最终所需要的Observable。
流程分析流程图总结
总体的流程图整理如下:

解答疑问
对于之前的疑问可以作答了。
第一个疑问: 我们调用接口的方法后是怎么发送请求的?这背后发生了什么?
Retrofit 使用了动态代理给我们定义的接口设置了代理,当我们调用接口的方法时,Retrofit 会拦截下来,然后经过一系列处理,比如解析方法的注解等,生成了 Call Request 等OKHttp所需的资源,最后交给 OkHttp 去发送请求, 此间经过 callAdapter,convertr 的处理,最后拿到我们所需要的数据。
第二个疑问: Retrofit 与 OkHttp 是怎么合作的?
在Retrofit 中,ServiceMethod 承载了一个 Http 请求的所有参数,OkHttpCall 为 okhttp3.call 的组合包装,由它们俩合作,生成用于 OkHttp所需的 Request以及okhttp3.Call,交给 OkHttp 去发送请求。(在本文环境下具体用的是 call.execute())
可以说 Retrofit 为 OkHttp 再封装了一层,并增添了不少功能以及扩展,减少了开发使用成本。
第三个疑问: Retrofit 中的数据究竟是怎么处理的?它是怎么返回 RxJava.Observable 的?
Retrofit 中的数据其实是交给了 callAdapter 以及 converter 去处理,callAdapter 负责把 okHttpCall 转成我们所需的 Observable类型(本文环境),converter负责把服务器返回的数据转成具体的实体类。
小结
Retrofit 的源码其实非常好跟也非常好理解,不像看 framework 的代码,跟着跟着就不见了。
另外 Retrofit的代码确实非常漂亮,将设计模式运用的可以说是炉火纯青,非常值得学习。