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…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
