Retrofit学习日记-构建Retrofit

174 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 1 天,点击查看活动详情

前言

如今 Retrofit 早已被扒的皮都不剩了,那为什么还要写此系列文章呢?

纸上得来终觉浅,绝知此事要躬行。

不管之前看过多少解析文章,终觉得理解的不够透彻,所以只有自己亲身阅读过源码,才能深有体会吧。


本系列文章基于目前最新的 Commit-2022/08/05

如何构建Retrofit?

构建 Retrofit 有以下两种方式:

  1. 创建 Retrofit 的内部类 Builder 的实例,调用 Builder 的 build 方法构建,
  2. 利用已有的 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 有两种注入方式:

  1. 调用 Buidler 的 client(OkHttpClient client) 方法,
  2. 调用 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,可以通过以下三种方式:

  1. 调用 baseUrl(URL baseUrl) 方法,
  2. 调用 baseUrl(String baseUrl) 方法,
  3. 调用 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.FactoryConverter.Factory 用于构建各种 Converter 实例,Converter 是 Retrofit 的强大功能之一,这个后面学到时再具体分析吧。

converterFactories 相关的方法有两个:

  1. 一个用于注入 Converter.Factory
  2. 一个用于获取 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.FactoryCallAdapter.Factory 用于构建各种 CallAdapter 实例,CallAdapter 也是 Retrofit 的强大功能之一,同样留到后面学到时再分析吧。

callAdapterFactories 相关的方法也有两个:

  1. 一个用于注入 CallAdapter.Factory
  2. 一个用于获取 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();
     }
     
     ......
 }
  1. 首先判断 baseUrl 不能为空,这里也对应在 baseUrl 字段的分析;
  2. 接下来判断是否注入了 callFactory,没有注入的话则创建一个默认的 OkHttpClient 实例,
  3. 下面在判断是否注入了 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);
 ​
     ......
 }
  1. 首先获取相应平台默认的 Converter.Factory 集合,并获取默认集合的大小,
  2. 其次构建一个 1 + this.converterFactories.size() + defaultConverterFactoriesSize 大小的 Converter.Factory 集合,
  3. 最后依次添加 BuiltInConverters(),外部注入的 converterFactories 以及平台默认的 defaultConverterFactories
 public Retrofit build() {
     ......
     
     return new Retrofit(
         callFactory,
         baseUrl,
         unmodifiableList(converterFactories),
         defaultConverterFactoriesSize,
         unmodifiableList(callAdapterFactories),
         defaultCallAdapterFactories.size(),
         callbackExecutor,
         validateEagerly);
 }

最后把 callAdapterFactoriescallAdapterFactories 转换为不可变集合,调用 Retrofit 的构造方法构建一个新的 Retrofit 实例。

总结

首先通过分析 Builder 类,我们学习了构建 Retrofit 实例所需的必需参数和可选参数。这样在不同的业务场景下,我们可以根据业务需求构建出适应业务场景的 Retrofit 实例。

其次阅读 Retrofit 源码,我们也学习了如何运用 Builder 构建器模式在所需参数较多,参数必选和可选时构建对象。

最后希望可以帮您更好的使用 Retrofit ~~