前几篇笔记记录的都是Retrofit2的使用,但是它内部到底干了什么我们还是啥都不知道。这让我们在使用Retrofit时,心里没底。所以这次我们就来简单过一遍retrofit的源码。
看Retrofit的源码对于毫无经验的我来说,第一步应该从哪呢?我决定从这开始:
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
apiService = retrofit.create(MovieService.class);
接下来我们要干什么,很自然的我们点进Builder()看看这里干了什么:
一、.Builder()
public Builder() {
this(Platform.get());
}
对,是的我们没有看错,就这么点东西。这么点东西我们也看到了两部分东西,一个是Platform.get(),另一个是this(…)。
- Platform.get()干了什么呢?继续跟进源码(不贴代码了,可以自己看一下)可以发现,这只是获取了设备平台信息;
- this()的用在这里相信大家都知道是什么意思,调用了一个重载的方法。
Builder(Platform platform) {
this.platform = platform;
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
}
看到这里我们就明白了,Builder()干了两件事:
- 创建了Platform,获取了设备平台信息;
- 添加了一个内部转换器工厂,可以看出来converterFactories是一个集合,而事实也是这样的。
private List<Converter.Factory> converterFactories = new ArrayList<>();
二、.baseUrl(url)
接着在看看这里的代码
public Builder baseUrl(String baseUrl) {
//baseUrl非空验证
checkNotNull(baseUrl, "baseUrl == null");
//创建HttpUrl对象
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
可以看到首先给我们的baseUrl来了个验证,如果是null的话我们会来一个NullPointerException;
然后,就是创建了一个HttpUrl对象,在这里会判断是否是http或https的URL,如果不是就返回null。
三、addConverterFactory()、addCallAdapterFactory
这两个干的事情类似
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* Add a call adapter factory for supporting service method returntypes other than {@link Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
分别添加转换器工厂和适配器工厂,而且这两个都是集合,因此很显然的转换器工厂和适配器工厂都是可以添加多个的。
四、.client()
创建client对象,
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
五、.build()创建Retrofit对象
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
初始化了必要的对象;
六、.create(xx.class)
xx.class是我们的接口类,我们看看源码里干了什么
public <T> T create(final Class<T> 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();
@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);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
我们看到Utils.validateServiceInterface(service);对我们传入的service进行了检验(service是我们写的接口类);
- 检查了我们的service是否是interface类型;
- 检查了我们的service内部的请求接口数量是否大于0。
validateEagerly:是否提前执行了方法参数的注解解析。
接下来我们看到了Proxy.newProxyInstance熟悉的同学,一下就看出来这是个动态代理;简单来说,当我们调用接口发起请求时,会走invoke里的代码;
我么在看看重写的invoke方法做了哪些操作。
ServiceMethod serviceMethod = loadServiceMethod(method);
在 这里创建了一个ServiceMethod实例对象;在loadServiceMethod(method)中创建了这个对象,传入Method method,这个method即我们请求接口的方法名。
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
//从集合中根据方法名 获取对应的ServiceMethod对象
result = serviceMethodCache.get(method);
//如果集合中没有方法 创建ServiceMethod对象 然后存放到集合中
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
serviceMethodCache是一个集合,存放了请求的method信息;
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
如果在集合中没有对应的该ServiceMethod对象,我们就创建一个;
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//获取接口方法的注解
this.methodAnnotations = method.getAnnotations();
//获取参数类型
this.parameterTypes = method.getGenericParameterTypes();
//获取参数注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
创建OkHttpCall对象
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
- serviceMethod:请求接口方法的信息;
- args:请求参数。
serviceMethod.callAdapter.adapt(okHttpCall);
调用了XXCallAdapter的方法adapt(),适配器工厂;在适配器工厂里进行了类型转换。见前篇Retrofit2.0的使用之自定义CallAdapter.Factory。