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("…...
星环科技推出DeepSeek全场景解决方案:即开即用、企业级部署、端侧智能三位一体
星环科技(688031.SH)正式发布DeepSeek全场景解决方案,全面覆盖个人用户、企业客户及行业场景需求,为用户提供从个人到企业、从云端到本地的全方位AI应用支持,为不同需求的用户提供了灵活、高效且安全的AI解决方案。 省…...
Redis缓存一致性难题:如何让数据库和缓存不“打架”?
标题:Redis缓存一致性难题:如何让数据库和缓存不“打架”?(附程序员脱发指南) 导言:当数据库和缓存成了“异地恋” 想象一下:你刚在美团下单了一份麻辣小龙虾,付款后刷新页面&#…...
动态部署Web应用程序与web.xml配置详解
文章目录 前言一、动态部署Web应用程序1.1 什么是动态部署?1.2 动态部署的步骤1.3 动态部署的优势 二、web.xml 配置文件2.1 什么是web.xml?2.2 web.xml 文件的结构2.2.1常见配置(1) 配置上下文参数(2) 配置Servlet(3)配置过滤器(…...
2025年软考报名费用是多少?全国费用汇总!
软考报名时间终于确定了!想要参加2025年软考的同学们注意啦!特别是那些一年只有一次考试机会的科目,千万不要错过哦!这里为大家整理了各地的报名时间、科目、费用等信息,快来看看吧! 一、2025年软考时间安…...
DeepSeek 15天指导手册——从入门到精通 PDF(附下载)
DeepSeek使用教程系列--DeepSeek 15天指导手册——从入门到精通pdf下载: https://pan.baidu.com/s/1PrIo0Xo0h5s6Plcc_smS8w?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/2e8de75027d3 《DeepSeek 15天指导手册——从入门到精通》以系统化学习路径为核心&…...
【Javascript】js精度丢失
当JS处理大整数或者浮点数的时候会出现精度丢失的情况。 Javascript的数字都使用双精度浮点数表示,遵循IEEE754标准 比如我遇到的问题,对一个小数的四舍五入,保留2位小数: 235.985≈235.98 235.9851≈235.99 原理请大家参考百度&…...
让Word插上AI的翅膀:如何把DeepSeek装进Word
在日常办公中,微软的Word无疑是我们最常用的文字处理工具。无论是撰写报告、编辑文档,还是整理笔记,Word都能胜任。然而,随着AI技术的飞速发展,尤其是DeepSeek的出现,我们的文字编辑方式正在发生革命性的变…...
秒杀系统的常用架构是什么?怎么设计?
架构 秒杀系统需要单独部署,如果说放在订单服务里面,秒杀的系统压力太大了就会影响正常的用户下单。 常用架构: Redis 数据倾斜问题 第一步扣减库存时 假设现在有 10 个商品需要秒杀,正常情况下,这 10 个商品应该均…...
【文件基础操作】小笔记
Step1: 现在项目文件夹(我的项目叫做RunPony)下创建一个a.txt文本文件,手动写入一些数字,保存 Step2: 现在在main.c内写一个基本的文件处理的程序 Step3: 现在已经知道如何打开关闭文件,下一步要搞懂如何读取txt内的…...
RabbitMQ系列(七)基本概念之Channel
RabbitMQ 中的 Channel(信道) 是客户端与 RabbitMQ 服务器通信的虚拟会话通道,其核心作用在于优化资源利用并提升消息处理效率。以下是其核心机制与功能的详细解析: 一、Channel 的核心定义 虚拟通信链路 Channel 是建立在 TCP 连…...
本地搭建Koodo Reader书库结合内网穿透打造属于自己的移动图书馆
文章目录 前言1. Koodo Reader 功能特点1.1 开源免费1.2 支持众多格式1.3 多平台兼容1.4 多端数据备份同步1.5 多功能阅读体验1.6 界面简洁直观 2. Koodo Reader安装流程2.1 安装Git2.2 安装Node.js2.3 下载koodo reader 3. 安装Cpolar内网穿透3.1 配置公网地址3.2 配置固定公网…...
DeepSeek R1 训练策略4个阶段解析
DeepSeek R1 训练策略解析 DeepSeek R1 训练策略解析1. 冷启动监督微调(Cold Start SFT)**该阶段的主要目标**: 2. 面向推理的强化学习(RL for Reasoning)**该阶段的主要目标**: 3. 拒绝采样和监督微调&…...
【博资考4】网安学院-硕转博考试内容
【博资考4】硕转博考试内容 - 网络安全与基础理论 写在最前面一. **21年硕转博面试内容回顾**网络、逆向、操作系统、攻防、漏洞1. **网络安全常见攻击方式及其防范措施**1.1 **DDoS攻击(分布式拒绝服务)**1.2 **SQL注入攻击**1.3 **XSS攻击(…...
30 分钟从零开始入门 CSS
HTML CSS JS 30分钟从零开始入门拿下 HTML_html教程-CSDN博客 30 分钟从零开始入门 CSS-CSDN博客 JavaScript 指南:从入门到实战开发-CSDN博客 前言 最近也是在复习,把之前没写的博客补起来,之前给大家介绍了 html,现在是 CSS 咯…...
C语言综合案例:学生成绩管理系统
C语言综合案例:学生成绩管理系统 需求 1.存储最多50名学生的信息(不使用结构体) 2.每个学生包含: 学号(字符数组)姓名(字符数组)3门课程成绩(一维数组) …...
使用python做http代理请求
有这样一个需求现在有两台A,B两台电脑组成了一个局域网,在A电脑上开发webjava应用,需要调用第三方接口做http请求,但是这个请求只能在B电脑上请求。 一种解决方案:自定义一个中间服务,在电脑B上运行一个简…...
数据库事务的基本要素(ACID)
数据库事务的基本要素(ACID) 在数据库管理系统(DBMS)中,事务(Transaction)是一个或多个数据库操作的集合,这些操作要么全部成功,要么全部失败。事务的目标是保证数据的一…...
DeepSeek R1满血+火山引擎详细教程
DeepSeek R1满血火山引擎详细教程 一、安装Cherry Studio。 Cherry Studio AI 是一款强大的多模型 AI 助手,支持 iOS、macOS 和 Windows 平台。可以快速切换多个先进的 LLM 模型,提升工作学习效率。下载地址 https://cherry-ai.com/ 认准官网,无强制注册。 这…...
大型语言模型技术对比:阿里Qwen qwq、DeepSeek R1、OpenAI o3与Grok 3
1. 引言 在人工智能(AI)领域中,大型语言模型(Large Language Models,简称LLM)近年来取得了显著的突破。从早期的GPT-3到如今的各种高级模型,这些技术不仅推动了自然语言处理(NLP&am…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
从零开始了解数据采集(二十八)——制造业数字孪生
近年来,我国的工业领域正经历一场前所未有的数字化变革,从“双碳目标”到工业互联网平台的推广,国家政策和市场需求共同推动了制造业的升级。在这场变革中,数字孪生技术成为备受关注的关键工具,它不仅让企业“看见”设…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...
