Android Retrofit 框架配置与构建模块深入源码分析(六)

一、引言

Retrofit 是一个在 Android 和 Java 开发中广泛使用的类型安全的 HTTP 客户端。它通过简洁的 API 设计,使得网络请求的处理变得高效且易于管理。配置与构建模块作为 Retrofit 的基础部分,承担着初始化和定制 Retrofit 实例的重要任务。开发者可以通过该模块对 Retrofit 进行多方面的配置,如设置基础 URL、添加转换器工厂、适配器工厂等,以满足不同项目的需求。下面我们将深入到源码级别,详细剖析 Retrofit 配置与构建模块的工作原理。

二、Retrofit 配置与构建的核心类:Retrofit.Builder

2.1 Retrofit.Builder 类概述

Retrofit.Builder 类是 Retrofit 配置与构建的核心类,它提供了一系列的方法用于设置 Retrofit 的各种参数,并最终构建出一个 Retrofit 实例。以下是 Retrofit.Builder 类的部分源码:

java

java 复制代码
public final class Retrofit {
    // 内部类,用于构建 Retrofit 实例
    public static final class Builder {
        // OkHttp 的 Call.Factory 实例,用于创建 HTTP 请求
        private okhttp3.Call.Factory callFactory;
        // 基础 URL
        private HttpUrl baseUrl;
        // 转换器工厂列表,用于处理请求和响应的数据转换
        private final List<Converter.Factory> converterFactories = new ArrayList<>();
        // 适配器工厂列表,用于将 Call 对象转换为其他类型
        private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
        // 回调执行器,用于处理回调操作
        private Executor callbackExecutor;
        // 是否提前验证接口方法
        private boolean validateEagerly;

        // 构造函数,初始化默认的转换器工厂和适配器工厂
        public Builder() {
            // 添加默认的转换器工厂,用于处理基本数据类型的转换
            converterFactories.add(new BuiltInConverters());
        }

        // 设置 Call.Factory 实例
        public Builder callFactory(okhttp3.Call.Factory factory) {
            this.callFactory = checkNotNull(factory, "factory == null");
            return this;
        }

        // 设置基础 URL
        public Builder baseUrl(String baseUrl) {
            checkNotNull(baseUrl, "baseUrl == null");
            // 解析基础 URL 为 HttpUrl 对象
            return baseUrl(HttpUrl.get(baseUrl));
        }

        // 设置基础 URL
        public Builder baseUrl(HttpUrl baseUrl) {
            checkNotNull(baseUrl, "baseUrl == null");
            // 检查基础 URL 是否以 / 结尾
            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;
        }

        // 添加转换器工厂
        public Builder addConverterFactory(Converter.Factory factory) {
            converterFactories.add(checkNotNull(factory, "factory == null"));
            return this;
        }

        // 添加适配器工厂
        public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
            callAdapterFactories.add(checkNotNull(factory, "factory == null"));
            return this;
        }

        // 设置回调执行器
        public Builder callbackExecutor(Executor executor) {
            this.callbackExecutor = checkNotNull(executor, "executor == null");
            return this;
        }

        // 设置是否提前验证接口方法
        public Builder validateEagerly(boolean validateEagerly) {
            this.validateEagerly = validateEagerly;
            return this;
        }

        // 构建 Retrofit 实例
        public Retrofit build() {
            if (baseUrl == null) {
                throw new IllegalStateException("Base URL required.");
            }

            okhttp3.Call.Factory callFactory = this.callFactory;
            if (callFactory == null) {
                // 如果没有设置 Call.Factory,默认使用 OkHttpClient 实例
                callFactory = new OkHttpClient();
            }

            Executor callbackExecutor = this.callbackExecutor;
            if (callbackExecutor == null) {
                // 如果没有设置回调执行器,默认使用 Android 主线程执行器
                callbackExecutor = platform.defaultCallbackExecutor();
            }

            // 创建不可变的转换器工厂列表
            List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
            // 添加默认的转换器工厂,用于处理字符串和字节数组的转换
            converterFactories.add(new BuiltInConverters());

            // 创建不可变的适配器工厂列表
            List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
            // 添加默认的适配器工厂,用于处理 Call 类型的返回值
            callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

            return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
                    unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
        }
    }
}

2.2 Retrofit.Builder 类的方法分析

2.2.1 构造函数

java

java 复制代码
public Builder() {
    converterFactories.add(new BuiltInConverters());
}

在构造函数中,会添加一个 BuiltInConverters 实例到转换器工厂列表中。BuiltInConverters 是一个内置的转换器工厂,用于处理基本数据类型的转换。

2.2.2 callFactory 方法

java

java 复制代码
public Builder callFactory(okhttp3.Call.Factory factory) {
    this.callFactory = checkNotNull(factory, "factory == null");
    return this;
}

该方法用于设置 Call.Factory 实例,Call.Factory 是 OkHttp 中的一个接口,用于创建 Call 对象,Call 对象代表一个 HTTP 请求。这里会对传入的 factory 进行非空检查,确保其不为空。

2.2.3 baseUrl 方法

java

java 复制代码
public Builder baseUrl(String baseUrl) {
    checkNotNull(baseUrl, "baseUrl == null");
    return baseUrl(HttpUrl.get(baseUrl));
}

public Builder baseUrl(HttpUrl baseUrl) {
    checkNotNull(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 方法用于设置基础 URL。第一个方法接收一个字符串类型的 baseUrl,会将其解析为 HttpUrl 对象后调用第二个方法。第二个方法会对 baseUrl 进行检查,确保其以 / 结尾,否则会抛出 IllegalArgumentException 异常。

2.2.4 addConverterFactory 方法

java

java 复制代码
public Builder addConverterFactory(Converter.Factory factory) {
    converterFactories.add(checkNotNull(factory, "factory == null"));
    return this;
}

该方法用于添加转换器工厂到转换器工厂列表中。转换器工厂用于创建转换器,转换器负责将请求参数序列化为 HTTP 请求体,以及将 HTTP 响应体反序列化为 Java 对象。这里会对传入的 factory 进行非空检查。

2.2.5 addCallAdapterFactory 方法

java

java 复制代码
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
    callAdapterFactories.add(checkNotNull(factory, "factory == null"));
    return this;
}

该方法用于添加适配器工厂到适配器工厂列表中。适配器工厂用于创建适配器,适配器负责将 Call 对象转换为其他类型,如 ObservableCompletable 等。这里会对传入的 factory 进行非空检查。

2.2.6 callbackExecutor 方法

java

java 复制代码
public Builder callbackExecutor(Executor executor) {
    this.callbackExecutor = checkNotNull(executor, "executor == null");
    return this;
}

该方法用于设置回调执行器,回调执行器用于处理回调操作。这里会对传入的 executor 进行非空检查。

2.2.7 validateEagerly 方法

java

java 复制代码
public Builder validateEagerly(boolean validateEagerly) {
    this.validateEagerly = validateEagerly;
    return this;
}

该方法用于设置是否提前验证接口方法。如果设置为 true,Retrofit 会在创建服务接口实例时对接口方法进行验证,而不是在调用方法时才验证。

2.2.8 build 方法

java

java 复制代码
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<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    converterFactories.add(new BuiltInConverters());

    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
            unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

build 方法用于构建 Retrofit 实例。在构建过程中,会进行一些必要的检查和默认值的设置:

  • 检查基础 URL 是否为空,如果为空则抛出 IllegalStateException 异常。
  • 如果没有设置 Call.Factory,则默认使用 OkHttpClient 实例。
  • 如果没有设置回调执行器,则使用平台默认的回调执行器。
  • 添加默认的转换器工厂和适配器工厂到相应的列表中。
  • 最后使用这些配置创建一个 Retrofit 实例并返回。

三、配置与构建模块的使用示例

3.1 基本配置

java

java 复制代码
Retrofit retrofit = new Retrofit.Builder()
       .baseUrl("https://api.example.com/")
       .build();

在这个示例中,我们只设置了基础 URL,其他配置使用默认值。build 方法会自动处理默认的 Call.Factory、回调执行器等配置。

3.2 自定义配置

java

java 复制代码
OkHttpClient okHttpClient = new OkHttpClient.Builder()
       .connectTimeout(10, TimeUnit.SECONDS)
       .readTimeout(10, TimeUnit.SECONDS)
       .writeTimeout(10, TimeUnit.SECONDS)
       .build();

Retrofit retrofit = new Retrofit.Builder()
       .baseUrl("https://api.example.com/")
       .callFactory(okHttpClient)
       .addConverterFactory(GsonConverterFactory.create())
       .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
       .callbackExecutor(Executors.newSingleThreadExecutor())
       .validateEagerly(true)
       .build();

在这个示例中,我们进行了更详细的配置:

  • 创建了一个自定义的 OkHttpClient 实例,并设置了连接超时、读取超时和写入超时时间。
  • 使用 callFactory 方法将自定义的 OkHttpClient 实例设置为 Call.Factory
  • 使用 addConverterFactory 方法添加了 GsonConverterFactory,用于处理 JSON 数据的转换。
  • 使用 addCallAdapterFactory 方法添加了 RxJava2CallAdapterFactory,用于将 Call 对象转换为 RxJava 的 Observable 等类型。
  • 使用 callbackExecutor 方法设置了一个单线程的执行器作为回调执行器。
  • 使用 validateEagerly 方法设置为提前验证接口方法。

四、配置与构建模块的高级用法

4.1 动态配置基础 URL

在某些情况下,我们可能需要根据不同的环境动态配置基础 URL。可以通过封装 Retrofit.Builder 来实现这一点:

java

java 复制代码
public class RetrofitClient {
    private static Retrofit retrofit;

    public static Retrofit getClient(String baseUrl) {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                   .baseUrl(baseUrl)
                   .addConverterFactory(GsonConverterFactory.create())
                   .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                   .build();
        }
        return retrofit;
    }
}

在使用时,可以根据不同的环境传入不同的基础 URL:

java

java 复制代码
Retrofit retrofit = RetrofitClient.getClient("https://api.example.com/");

4.2 配置拦截器

可以通过自定义 OkHttpClient 并添加拦截器来实现对 HTTP 请求和响应的拦截和处理。以下是一个添加日志拦截器的示例:

java

java 复制代码
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import java.io.IOException;

public class RetrofitConfig {
    public static Retrofit getRetrofit() {
        // 创建日志拦截器
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        // 创建自定义的 OkHttpClient 并添加拦截器
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
               .addInterceptor(loggingInterceptor)
               .addInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request originalRequest = chain.request();
                        // 可以在这里对请求进行修改,如添加请求头
                        Request newRequest = originalRequest.newBuilder()
                               .header("Authorization", "Bearer your_token")
                               .build();
                        return chain.proceed(newRequest);
                    }
                })
               .build();

        return new Retrofit.Builder()
               .baseUrl("https://api.example.com/")
               .callFactory(okHttpClient)
               .addConverterFactory(GsonConverterFactory.create())
               .build();
    }
}

在这个示例中,我们添加了一个日志拦截器用于打印请求和响应的详细信息,还添加了一个自定义的拦截器用于在请求中添加请求头。

五、配置与构建模块的异常处理

5.1 基础 URL 为空异常

build 方法中,如果基础 URL 为空,会抛出 IllegalStateException 异常:

java

java 复制代码
if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
}

这是为了确保 Retrofit 实例在构建时必须有一个有效的基础 URL。

5.2 其他异常

在配置过程中,如果传入的参数为空,如 callFactoryconverterFactorycallAdapterFactorycallbackExecutor 等,会在相应的设置方法中抛出 NullPointerException 异常,因为这些方法都进行了非空检查:

java

java 复制代码
public Builder callFactory(okhttp3.Call.Factory factory) {
    this.callFactory = checkNotNull(factory, "factory == null");
    return this;
}

六、配置与构建模块的性能优化

6.1 单例模式

为了避免重复创建 Retrofit 实例,可以使用单例模式。以下是一个简单的单例实现:

java

java 复制代码
public class RetrofitSingleton {
    private static Retrofit retrofit;

    private RetrofitSingleton() {}

    public static synchronized Retrofit getInstance() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                   .baseUrl("https://api.example.com/")
                   .addConverterFactory(GsonConverterFactory.create())
                   .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                   .build();
        }
        return retrofit;
    }
}

使用单例模式可以减少内存开销,提高性能。

6.2 合理配置 OkHttpClient

OkHttpClient 是 Retrofit 底层使用的 HTTP 客户端,合理配置 OkHttpClient 可以提高性能。例如,可以设置连接池、缓存等:

java

java 复制代码
OkHttpClient okHttpClient = new OkHttpClient.Builder()
       .connectTimeout(10, TimeUnit.SECONDS)
       .readTimeout(10, TimeUnit.SECONDS)
       .writeTimeout(10, TimeUnit.SECONDS)
       .connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES))
       .cache(new Cache(cacheDirectory, cacheSize))
       .build();

在这个示例中,我们设置了连接超时、读取超时和写入超时时间,还设置了连接池和缓存。连接池可以复用已经建立的连接,减少连接建立的开销;缓存可以避免重复的网络请求,提高响应速度。

七、配置与构建模块的未来发展趋势

7.1 与更多的 HTTP 客户端集成

目前 Retrofit 主要与 OkHttp 集成,未来可能会支持更多的 HTTP 客户端,如 HttpURLConnection 等,以满足不同开发者的需求。

7.2 更简洁的配置方式

随着 Android 开发的不断发展,可能会出现更简洁的配置方式,减少开发者的配置工作量。例如,通过注解或配置文件来进行配置。

7.3 更好的性能优化

未来的配置与构建模块可能会进行更多的性能优化,如减少初始化时间、降低内存开销等。可以通过优化内部的数据结构和算法来实现这些优化。

7.4 增强的错误处理和调试功能

配置与构建模块可能会提供更详细的错误信息和调试工具,帮助开发者更快地定位和解决问题。例如,在异常信息中提供更多的上下文信息,或者提供可视化的调试工具。

八、总结

Retrofit 的配置与构建模块是整个框架的基础,它提供了丰富的配置选项,使得开发者可以根据不同的需求对 Retrofit 进行定制。通过深入分析 Retrofit.Builder 类的源码,我们了解了各个配置方法的作用和实现细节。在实际开发中,我们可以根据项目的需求进行合理的配置,如设置基础 URL、添加转换器工厂和适配器工厂、配置拦截器等。同时,我们还可以通过单例模式和合理配置 OkHttpClient 来提高性能。随着 Android 开发的不断发展,配置与构建模块也可能会不断改进和完善,为开发者提供更好的开发体验。

相关推荐
安卓理事人11 分钟前
安卓LinkedBlockingQueue消息队列
android
万能的小裴同学1 小时前
Android M3U8视频播放器
android·音视频
q***57742 小时前
MySql的慢查询(慢日志)
android·mysql·adb
JavaNoober2 小时前
Android 前台服务 "Bad Notification" 崩溃机制分析文档
android
城东米粉儿3 小时前
关于ObjectAnimator
android
zhangphil4 小时前
Android渲染线程Render Thread的RenderNode与DisplayList,引用Bitmap及Open GL纹理上传GPU
android
火柴就是我5 小时前
从头写一个自己的app
android·前端·flutter
lichong9516 小时前
XLog debug 开启打印日志,release 关闭打印日志
android·java·前端
用户69371750013846 小时前
14.Kotlin 类:类的形态(一):抽象类 (Abstract Class)
android·后端·kotlin
火柴就是我7 小时前
NekoBoxForAndroid 编译libcore.aar
android