构建Retrofit
前言
如今 Retrofit 早已被扒的皮都不剩了,那为什么还要写此系列文章呢?
纸上得来终觉浅,绝知此事要躬行。
不管之前看过多少解析文章,终觉得理解的不够透彻,所以只有自己亲身阅读过源码,才能深有体会吧。
本系列文章基于目前最新的 Commit-2022/08/05
如何构建Retrofit?
构建 Retrofit 有以下两种方式:
- 创建 Retrofit 的内部类 Builder 的实例,调用 Builder 的
build
方法构建, - 利用已有的 Retrofit 实例,调用
newBuiler
方法创建 Builder 实例,调用 Builder 的build
方法构建。
Retrofit retrofit = new Retrofit.Builder().build(); // 第一种方式
retrofit = retrofit.newBuilder().build(); // 第二种方式
可以看出上述两种方式最终都是调用 Builder 的 build
方法来构建 Retrofit。
构建入口的唯一性,利用后续的维护。
Builder
Builder 类是 Retrofit 的静态内部类,它唯一的作用就是帮助我们构建 Retrofit。我们通过给 Builder 类传入不同的参数,来构建不能功能的 Retrofit 实例。
下面我们逐个分析下 Builder 类中的字段和方法吧。
callFactory
callFactory
字段的类型是 okhttp3.Call.Factory
,说明它是 okhttp3 中的一个类,此类是一个接口且其中仅有一个接口方法:
// okhttp3.Call.Factory
interface Factory {
Call newCall(Request request);
}
通过上述源码可以看出此接口唯一的作用就是构建一个新的 Call 实例。
由于 Retrofit 是基于 okhttp3 的封装库,因此它需要通过 callFactory
字段来构建 okhttp3 的 Call 实例。
callFactory
有两种注入方式:
- 调用 Buidler 的
client(OkHttpClient client)
方法, - 调用 Buidler 的
callFactory(okhttp3.Call.Factory factory)
方法。
public Builder client(OkHttpClient client) {
return callFactory(Objects.requireNonNull(client, "client == null"));
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = Objects.requireNonNull(factory, "factory == null");
return this;
}
以上两种方式,其中第一种方式是我们经常使用的,在外部构建好一个 OkHttpClient
实例传入 Builder,其实 OkHttpClient
实现了 okhttp3.Call.Factory
接口,所以它才能赋值给 callFactory
字段。
baseUrl
baseUrl
字段的类型是 okhttp3.HttpUrl
。
在 Builder 类的注释中说:在调用 build()
方法前必须调用 baseUrl()
方法。其他方法的调用都是可选的。
这足以说明 baseUrl
的重要性。
要注入 baseUrl
,可以通过以下三种方式:
- 调用
baseUrl(URL baseUrl)
方法, - 调用
baseUrl(String baseUrl)
方法, - 调用
baseUrl(HttpUrl baseUrl)
方法。
// 第一种方式
public Builder baseUrl(URL baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl.toString()));
}
// 第二种方式
public Builder baseUrl(String baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
// 第三种方式
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
其中我们最常用的就数第二种方式了。
观察上面源码的可以看出,前两种方式都间接调用了第三种方式。在第三种方式中,判断了 baseUrl
是否以 /
结尾,所以我们注入 baseUrl
时,通常以 /
结尾,比如 https://github.com/
。
converterFactories
converterFactories
字段是个集合类型,它存储的是 Converter.Factory
。Converter.Factory
用于构建各种 Converter
实例,Converter
是 Retrofit 的强大功能之一,这个后面学到时再具体分析吧。
与 converterFactories
相关的方法有两个:
- 一个用于注入
Converter.Factory
, - 一个用于获取
converterFactories
的可修改集合。
// 注入 `Converter.Factory`
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
// 获取 `converterFactories` 的可修改集合
public List<Converter.Factory> converterFactories() {
return this.converterFactories;
}
callAdapterFactories
callAdapterFactories
字段也是集合类型,它存储的是 CallAdapter.Factory
。CallAdapter.Factory
用于构建各种 CallAdapter
实例,CallAdapter
也是 Retrofit 的强大功能之一,同样留到后面学到时再分析吧。
与 callAdapterFactories
相关的方法也有两个:
- 一个用于注入
CallAdapter.Factory
, - 一个用于获取
callAdapterFactories
的可修改集合。
// 注入 `CallAdapter.Factory`
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
// 获取 `callAdapterFactories` 的可修改集合
public List<CallAdapter.Factory> callAdapterFactories() {
return this.callAdapterFactories;
}
callbackExecutor
callbackExecutor
的类型是 Executor
。它的作用是把 Callback
回调接口中的两个方法抛到指定的线程运行。
与 callbackExecutor
相关的只有一个注入方法:
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = Objects.requireNonNull(executor, "executor == null");
return this;
}
validateEagerly
validateEagerly
目前是最后一个字段,Boolean 类型。主要用于在 create()
方法内的早期校验与接口方法与参数解析。
与 validateEagerly
相关的仅有一个注入方法:
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
build()
通过上面介绍的几个字段,我们已经了解构建 Retrofit 需要哪些必要参数,哪些是可选参数,现在我们可以调用 build()
方法来构建一个新的 Retrofit 实例了。
build()
方法比较长,我们一步步分析吧。
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
Platform platform = Platform.get();
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
......
}
- 首先判断
baseUrl
不能为空,这里也对应在baseUrl
字段的分析; - 接下来判断是否注入了
callFactory
,没有注入的话则创建一个默认的OkHttpClient
实例, - 下面在判断是否注入了
callbackExecutor
,没有注入的话获取相应平台默认的Executor
。Android 平台默认在主线程。
public Retrofit build() {
......
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
List<? extends CallAdapter.Factory> defaultCallAdapterFactories =
platform.createDefaultCallAdapterFactories(callbackExecutor);
callAdapterFactories.addAll(defaultCallAdapterFactories);
......
}
接下来构建 callAdapterFactories
集合的副本,并添加相应平台默认的 CallAdapter.Factory
。
public Retrofit build() {
......
List<? extends Converter.Factory> defaultConverterFactories =
platform.createDefaultConverterFactories();
int defaultConverterFactoriesSize = defaultConverterFactories.size();
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size() + defaultConverterFactoriesSize);
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(defaultConverterFactories);
......
}
- 首先获取相应平台默认的
Converter.Factory
集合,并获取默认集合的大小, - 其次构建一个
1 + this.converterFactories.size() + defaultConverterFactoriesSize
大小的Converter.Factory
集合, - 最后依次添加
BuiltInConverters()
,外部注入的converterFactories
以及平台默认的defaultConverterFactories
。
public Retrofit build() {
......
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
defaultConverterFactoriesSize,
unmodifiableList(callAdapterFactories),
defaultCallAdapterFactories.size(),
callbackExecutor,
validateEagerly);
}
最后把 callAdapterFactories
和 callAdapterFactories
转换为不可变集合,调用 Retrofit
的构造方法构建一个新的 Retrofit
实例。
总结
首先通过分析 Builder 类,我们学习了构建 Retrofit
实例所需的必需参数和可选参数。这样在不同的业务场景下,我们可以根据业务需求构建出适应业务场景的 Retrofit
实例。
其次阅读 Retrofit 源码,我们也学习了如何运用 Builder 构建器模式在所需参数较多,参数必选和可选时构建对象。
最后希望可以帮您更好的使用 Retrofit ~~