看过很多篇 Retrofit 的源码分析文章,但是别人一问起来总是讲不清楚到底 Retrofit 是怎么个流程,所以还是得自己亲自去看看源码,一步一步的分析。果然只有亲自动手实践,才有自己的收获。
告诫自己,慢慢来,会很快。
目录
Retrofit 简介
Retrofit 源码开头的解释
* Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to
* define how requests are made. Create instances using {@linkplain Builder
* the builder} and pass your interface to {@link #create} to generate an implementation.
Retrofit 利用方法上的注解将接口转化成一个 HTTP 请求。
简单知道是什么了之后,我们对此提出疑问:
接下来我们将从 Retrofit 的使用作为入口分析。
Retrofit 分析
具体使用
首先建立 API 接口类:
interface GankApi {
String host = "http://gank.io/api/data/";
("Android/10/{page}")
Call getAndroid(@Path("page") int page);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GankApi.host)
.addConverterFactory(GsonConverterFactory.create())
.build();
GankApi gankApi = retrofit.create(GankApi.class);
Call call = gankApi.getAndroid(1);
call.enqueue(Callback callback)
简单的使用就是这样的流程。现在我们开始层层剖析。
工具箱:Retrofit.Builder()
private Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private List converterFactories = new ArrayList<>();
private List adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
创建 Retrofit 的实例,进行一些配置,这里我们不用多说。但是有一个参数必须得讲讲。
在构建 Retrofit 的时候,会对当前使用平台进行判断,Java8,Android,iOS。
我们看看 Android 平台的代码:
static class Android extends Platform {
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
public void execute(Runnable r) {
handler.post(r);
从代码中我们得知两点:
- 在 Android 里我们默认使用的 CallAdapter 是
ExecutorCallAdapterFactory()
它会返回的是 Call.class。关于ExecutorCallAdapterFactory()
我们稍后再说,你先知道这是 Android 默认 CallAdapter 就好。 - 默认的 Callback 是在主线程。
外壳:Create()
GankApi gankApi = retrofit.create(GankApi.class);
我在源码里写好了注释:
public T create(final Class service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
});
切合我们实际运用来看看顺序:
GankApi gankApi = retrofit.create(GankApi.class);
—->
return (T) Proxy.newProxyInstance(...){...}
—->
Call call = gankApi.getAndroid(1);
—->
public Object invoke(...){...}
调用代理类的invoke()
。
直到这里我们已经宏观地了解 Retrofit 是怎样的一个流程。
达成 初窥门径 成就。
千万别骄傲,为了以后走的更远更稳,我们得好好筑基,上面我们用到的是动态代理,强烈建议认真阅读两篇文章。
结构:ServiceMethod
Retrofit 有一个双链表用来缓存方法private final Map serviceMethodCache = new LinkedHashMap<>();
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
return result;
我们发现主要的方法是 new ServiceMethod.Builder(this, method).build();
,所以接下来我们深入看看如何 解析注解 以及 构建请求方法 。
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
这里的源码很长,做了很多异常处理,我截取重点来分析下。
callAdapter = createCallAdapter();
responseConverter = createResponseConverter();
一个是用来发送请求的 client ,一个是结果的转换器(Gson,FastJson …)之类,后面我们再讲这个。
上层配置就是当我们调用 Retrofit 的 addConverterFactory()
和 addCallAdapterFactory()
,内部会自动使用我们定义的组件。
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
在这里可以看到遍历我们使用方法的注解,并且解析他们。parseMethodAnnotation()
内部就是解析好 HTTP 的请求方式。
为了篇幅大小,可以在 源码 里看看具体的操作。
同时也可以看看 http 包下注解用到的接口,你会发现 @Retention(RUNTIME)
所以,从这里我们就可以明白,Retrofit 是在在运行期通过反射访问到这些注解的。
请求方法参数,请求客户端,返回值转换,我们都定义好了之后,便完成最后一步,构建好适合请求客户端的请求方法,Retrofit 默认的是 okhttpCall 。
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
最后将 call 返回给上层,用户调用方法进行请求。