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;// 基础 URLprivate 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;}// 设置基础 URLpublic Builder baseUrl(String baseUrl) {checkNotNull(baseUrl, "baseUrl == null");// 解析基础 URL 为 HttpUrl 对象return baseUrl(HttpUrl.get(baseUrl));}// 设置基础 URLpublic 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() {@Overridepublic 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 开发的不断发展,配置与构建模块也可能会不断改进和完善,为开发者提供更好的开发体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

80.Dictionary 字典 C#例子

使用 C# 中的 Dictionary 数据结构 在 C# 中&#xff0c;Dictionary<TKey, TValue> 是一个非常强大的数据结构&#xff0c;用于存储键值对。它提供了高效的查找、插入和删除操作&#xff0c;适用于需要快速访问数据的场景。本文将通过一个简单的示例&#xff0c;介绍如何…

tomcat负载均衡配置

这里拿Nginx和之前做的Tomcat 多实例来实现tomcat负载均衡 1.准备多实例与nginx tomcat单机多实例部署-CSDN博客 2.配置nginx做负载均衡 upstream tomcat{ server 192.168.60.11:8081; server 192.168.60.11:8082; server 192.168.60.11:8083; } ser…

C语言中scanf(“%c“,s)会出现的问题

scanf("%c%c", &word[0], &word[1]);的行为与输入缓冲区的内容密切相关。你提到输入ab后&#xff0c;word[0]是\n&#xff0c;这通常是因为输入缓冲区中残留了换行符&#xff08;\n&#xff09;。 一、原因分析 换行符残留 若在输入ab之前有其他输入操作&a…

SealOS部署k8s集群(单节点)

一、 先决条件 每个集群节点应该有不同的主机名。需要在 K8s 集群的第一个 master 节点上运行 sealos run 命令。建议使用干净的操作系统来创建集群。不要自己装 Docker&#xff01;支持大多数 Linux发行版&#xff0c;但内核版本建议5以上。例如&#xff1a;Ubuntu、CentOS、…

Linux 服务器安全配置:密码复杂度与登录超时设置

Linux服务器安全配置指南:密码复杂度与登录超时设置 一、密码复杂度设置 通过PAM模块pam_cracklib.so实现密码强度策略,配置文件: system-auth该文件主要用于定义系统范围内的认证策略,涵盖了用户登录、su 命令切换用户、sudo 权限提升等多种认证场景。当用户尝试进行系…

AI Agent开发框架分析:前端视角

1. Mastra (https://mastra.ai/docs) 优点&#xff1a; 提供直观的界面构建器&#xff0c;适合无代码/低代码开发支持JavaScript/TypeScript&#xff0c;可直接集成到前端项目可视化工作流设计&#xff0c;降低入门门槛内置多种UI组件&#xff0c;加速前端开发 缺点&#xf…

linux上使用unsloth微调大模型的环境踩坑之路-4070ti、4090

我们实验室有2套环境 一套&#xff1a;4070ti。安装了cuda12.4 一套&#xff1a;3张4090.安装了cuda12.4 现在开始给第一套装能运行unsloth能运行的环境 第一步&#xff1a;开始创建虚拟环境 conda create -n test_env python3.11 第二步&#xff1a;进入虚拟环境 conda activa…

网络安全演练有哪些形式

OPENVAS使用 1、确定指定IP是否能ping通 2、创建扫描目标 3、创建扫描任务&#xff08;scan management →newtask&#xff09; 4、开始任务start 5、查看扫描细节 6、查看扫描结果&#xff0c;包含漏洞详细信息&#xff0c;亦可到处PDF文件 7、导出扫描结果报告 8、为…

ConcurrentModificationException:检测到并发修改完美解决方法

&#x1f6a6; ConcurrentModificationException&#xff1a;检测到并发修改完美解决方法 &#x1f4a1; 摘要 1. 什么是ConcurrentModificationException&#xff1f;&#x1f914; 2. ConcurrentModificationException的常见场景 &#x1f6a6; 2.1 使用for-each循环遍历集合…

电路原理(电容 集成电路NE555)

电容 1.特性&#xff1a;充放电&#xff0c;隔直流&#xff0c;通交流 2.电容是通过聚集正负电荷来存储电能的 3.电容充放电过程可等效为导通回路 4.多电容并联可以把容量叠加&#xff0c;但是多电容串联就不会&#xff0c;只会叠加电容的耐压值。 6.电容充放电时相当于通路&a…

深入解析 React 最新特性:革新、应用与最佳实践

深入解析 React 最新特性&#xff1a;革新、应用与最佳实践 1. 引言 React 作为前端开发的核心技术之一&#xff0c;近年来不断推出 新的 API 和优化机制&#xff0c;从 Concurrent Rendering&#xff08;并发模式&#xff09; 到 Server Components&#xff08;服务器组件&a…

【氮化镓】高输入功率应力诱导的GaN 在下的退化LNA退化

2019年,中国工程物理研究院电子工程研究所的Tong等人基于实验与第一性原理计算方法,研究了Ka波段GaN低噪声放大器(LNA)在高输入功率应力下的退化机制。实验结果表明,在27 GHz下施加1 W连续波(CW)输入功率应力后,LNA的增益下降约1 dB,噪声系数(NF)增加约0.7 dB。进一…

C#程序员接口调用工具与方法

作为专注于接口调用的C#软件工程师&#xff0c;以下工具和方法能显著提升开发效率与代码质量&#xff1a; 一、接口开发与测试自动化工具 1. API测试与Mock工具 Postman Newman 支持RESTful/GraphQL接口调试与自动化测试&#xff0c;通过集合&#xff08;Collection&#xf…

Spring Boot项目中集成sa-token实现认证授权和OAuth 2.0第三方登录

OAuth 2.0第三方登录 OAuth 2.0 是一种授权协议&#xff0c;允许第三方应用在不暴露用户密码的情况下访问用户的资源。它通常用于第三方登录场景&#xff0c;例如使用GitHub、Google等社交平台进行登录。 在sa-token框架中&#xff0c;OAuth 2.0第三方登录可以通过集成sa-tok…

数字化新零售与 AI 大模型,如何重塑大健康赛道?​

在数字化浪潮中&#xff0c;大健康赛道正经历深刻变革。数字化新零售营销模式的兴起&#xff0c;与 AI 大模型的强大能力相结合&#xff0c;为大健康领域带来了全新的发展机遇。 数字化新零售营销模式融合线上线下&#xff0c;运用大数据、云计算分析消费者行为&#xff0c;实…

高速PCB设计(布线设计)

以下是针对高速PCB布线设计的综合笔记&#xff0c;结合用户提供的设计规范及行业通用原则整理而成&#xff1a; 一、关键信号布线原则 布线优先级 顺序&#xff1a;射频信号&#xff1e;中/低频信号&#xff1e;时钟信号&#xff1e;高速信号射频信号需包地处理&#xff0c;线…

宇树ROS1开源模型在ROS2中Gazebo中仿真

以GO1为例 1. CMakelists.txt更新语法 cmake_minimum_required(VERSION 3.8) project(go1_description) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find…

嵌入式学习第二十四天--网络 服务器

服务器模型 tcp服务器: socket bind listen accept recv/send close 1.支持多客户端访问 //单循环服务器 socket bind listen while(1) { accept while(1) { recv/send } } close 2.支持多客户端同时访问 (并发能力) 并发服务器 socket bind …

使用GPTQ量化Llama-3-8B大模型

使用GPTQ量化8B生成式语言模型 服务器配置&#xff1a;4*3090 描述&#xff1a;使用四张3090&#xff0c;分别进行单卡量化&#xff0c;多卡量化。并使用SGLang部署量化后的模型&#xff0c;使用GPTQ量化 原来的模型精度为FP16&#xff0c;量化为4bit 首先下载gptqmodel量化…

防汛应急包,快速响应,守护安全

根据中国水利部统计&#xff0c;自1949年以来&#xff0c;我国几乎每年都面临洪水威胁&#xff0c;其中20世纪90年代后洪涝灾害频率显著增加&#xff0c;仅1990-2009年间就发生超4000起较大灾害&#xff0c;直接经济损失近3万亿元&#xff0c;受灾人口达20亿人次。在2020年长江…