跳至主要內容

构建Retrofit

guodongAndroid大约 5 分钟

前言

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

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

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


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

如何构建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 ~~