当前位置: 首页 > news >正文

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

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

public Builder() {
    converterFactories.add(new BuiltInConverters());
}

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

2.2.2 callFactory 方法

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

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

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

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

2.2.5 addCallAdapterFactory 方法

java

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

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

2.2.6 callbackExecutor 方法

java

public Builder callbackExecutor(Executor executor) {
    this.callbackExecutor = checkNotNull(executor, "executor == null");
    return this;
}

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

2.2.7 validateEagerly 方法

java

public Builder validateEagerly(boolean validateEagerly) {
    this.validateEagerly = validateEagerly;
    return this;
}

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

2.2.8 build 方法

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

Retrofit retrofit = new Retrofit.Builder()
       .baseUrl("https://api.example.com/")
       .build();

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

3.2 自定义配置

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

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

Retrofit retrofit = RetrofitClient.getClient("https://api.example.com/");

4.2 配置拦截器

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

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

if (baseUrl == null) {
    throw new IllegalStateException("Base URL required.");
}

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

5.2 其他异常

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

java

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

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

6.1 单例模式

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

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

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 开发的不断发展,配置与构建模块也可能会不断改进和完善,为开发者提供更好的开发体验。

相关文章:

  • 微软程序控制机制WDAC
  • 自动化的多线程实现
  • Spring中的对象创建与生命周期管理
  • Gateway:网关路由与登录鉴权
  • 手机端安装包签名原理
  • 下载文件,文件名乱码问题
  • sql server 2016 版本补丁说明
  • 在unsloth框架下的基于医疗deepseek模型微调
  • 257. 二叉树的所有路径(递归+回溯)
  • 树莓派 调用摄像头
  • clickhouse集群部署保姆级教程
  • C++相关数据结构的API调用
  • qemu-kvm源码解析-内存虚拟化
  • CUDA error code 201:invalid device context
  • 《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(32)万剑归宗破妖阵 - 最长递增子序列(LIS)
  • 有哪些好用的AI视频加工创作网站
  • SpringBoot整合JPA
  • 使用 ConfigMaps 可以优化 Spring Boot应用
  • 08 | 实现版本号打印功能
  • 线索二叉树构造及遍历算法
  • 法治日报整版聚焦:儿童能否成为短视频主角?该如何监管?
  • 筑牢安全防线、提升应急避难能力水平,5项国家标准发布
  • 中拉论坛部长级会议为何悬挂海地和圣卢西亚的国旗?外交部回应
  • 新剧|《藏海传》定档,《折腰》《人生若如初见》今日开播
  • 人大新闻教育70年丨16759门课程里的时代密码
  • 民企老板被错羁212天续:申请国赔千万余元,要求恢复名誉赔礼道歉