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——>同步请求

        特点

  1. 阻塞线程
    请求发送后,当前线程会阻塞,直到服务器返回响应或超时。

  2. 直接返回结果
    通过 execute() 方法直接返回 Response 对象,无需回调。

  3. 线程管理
    不能在主线程中执行,否则会触发 NetworkOnMainThreadException 异常。同步请求必须在后台线程中执行,可以使用 ThreadExecutorService 或 RxJava 等工具管理线程。

  4. 资源释放
    Response 对象实现了 Closeable 接口,使用 try-with-resources 语法确保资源释放。

  5. 超时设置
    默认超时为 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 的响应式编程模型,用于处理异步数据流。其优势包括:

    • 链式调用:通过操作符(如 mapflatMap)简化复杂逻辑。
    • 线程调度:通过 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

    FlowableObservable是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))

    性能优化建议

    1. 混合使用策略
      对核心业务接口使用Flowable+BUFFER策略,非核心功能使用Observable

    2. 动态缓存控制
      通过rx2.buffer-size参数调整Flowable缓存池:

      System.setProperty("rx2.buffer-size", "256");  // 默认128[7](@ref)
    3. 生命周期管理
      使用CompositeDisposable统一释放资源:

      CompositeDisposable disposables = new CompositeDisposable();disposables.add(api.getDataStream().subscribe(data -> {...}));

    通过合理选择Flowable与Observable,可使Retrofit网络层在保证稳定性的同时获得最佳性能。可以在金融交易、物联网等高频场景优先采用Flowable,而在常规业务API中使用Observable以降低复杂度。

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

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

    相关文章

    每日Attention学习24——Strip Convolution Block

    模块出处 [TIP 21] [link] CoANet: Connectivity Attention Network for Road Extraction From Satellite Imagery 模块名称 Strip Convolution Block (SCB) 模块作用 多方向条形特征提取 模块结构 模块特点 类PSP设计&#xff0c;采用四个并行分支提取不同维度的信息相比于…

    用FileZilla Server 1.9.4给Windows Server 2025搭建FTP服务端

    FileZilla Server 是一款免费的开源 FTP 和 FTPS 服务器软件&#xff0c;分为服务器版和客户端版。服务器版原本只支持Windows操作系统&#xff0c;比如笔者曾长期使用过0.9.60版&#xff0c;那时候就只支持Windows操作系统。当时我们生产环境对FTP稳定性要求较高&#xff0c;比…

    es-head(es库-谷歌浏览器插件)

    1.下载es-head插件压缩包&#xff0c;并解压缩 2.谷歌浏览器添加插件 3.使用

    健康检查、k8s探针、Grails+Liquibase框架/health 404 Not Found排查及解决

    概述 健康检查对于一个pod而言&#xff0c;其重要性不言而喻。 k8s通过探针来实现健康检查。 探针 k8s提供三种探针&#xff1a; 存活探针&#xff1a;livenessProbe就绪探针&#xff1a;readinessProbe启动探针&#xff1a;startupProbe 存活探针 存活探针决定何时重启…

    5个GitHub热点开源项目!!

    1.自托管 Moonlight 游戏串流服务&#xff1a;Sunshine 主语言&#xff1a;C&#xff0c;Star&#xff1a;14.4k&#xff0c;周增长&#xff1a;500 这是一个自托管的 Moonlight 游戏串流服务器端项目&#xff0c;支持所有 Moonlight 客户端。用户可以在自己电脑上搭建一个游戏…

    【Linux C | 时间】localtime 的介绍、死机、死锁问题以及 localtime_r 函数的时区问题

    &#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

    122. 买卖股票的最佳时机 II 反向递推的方法

    下面是将你提供的代码整理成一篇Markdown格式的博客内容&#xff1a; 股票买卖的最大利润 问题描述 给定一个整数数组 prices&#xff0c;其中 prices[i] 是股票在第 i 天的价格。你可以选择在某一天买入股票&#xff0c;并在之后的某一天卖出股票。要求计算出你能够获得的最…

    详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)

    目录 步骤一&#xff1a;首先确认自己是否已经安装JDK步骤二&#xff1a;下载安装Tomcat步骤三&#xff1a;Tomcat配置环境变量步骤四&#xff1a;验证Tomcat配置是否成功步骤五&#xff1a;为IDEA配置Tomcat 步骤一&#xff1a;首先确认自己是否已经安装JDK jdk各版本通用安…

    html中的css

    css &#xff08;cascading style sheets&#xff0c;串联样式表&#xff0c;也叫层叠样式表&#xff09; css规范一般约定&#xff1a; 1.存放CSS样式文件的目录一般命名为style或css。 2.在项目初期&#xff0c;会把不同类别的样式放于不同的CSS文件&#xff0c;是为了CSS编…

    前端项目配置初始化

    creat-vue 安装 https://cn.vuejs.org/guide/quick-start.html 官网复制npm安装语句 cmd窗口创建文件夹 npm create vue3.12.2安装webstorm启动vue项目 https://www.jetbrains.com/webstorm/download/other.html 2024.3.2.1 安装依赖 下载包node_modules package 运行服…

    Java注解的原理

    目录 问题: 作用&#xff1a; 原理&#xff1a; 注解的限制 拓展&#xff1a; 问题: 今天刷面经&#xff0c;发现自己不懂注解的原理&#xff0c;特此记录。 作用&#xff1a; 注解的作用主要是给编译器看的&#xff0c;让它帮忙生成一些代码&#xff0c;或者是帮忙检查…

    seacmsv9注入管理员账号密码+orderby+limit

    seacmsv9注入管理员账号密码 安装海洋CMS&#xff08;seacms&#xff09; 将upload文件夹里的文件全部上传至网页服务器后&#xff0c;执行以下操作: 请运行http://域名/install/index.php进行程序安装 SQL语句尝试注入 http://127.0.0.1/upload/comment/api/index.php?g…

    【构建工具】Gradle Kotlin DSL中的大小写陷阱:BuildConfigField

    在Android开发当中&#xff0c;BuildConfig是一个非常有用的功能&#xff0c;它允许我们在构建过程中定义常量&#xff0c;并在运行时使用它们。But&#xff01;&#xff01;当我们从传统的Groovy DSL迁移到Kotlin DSL时或者被Android Studio坑的时候&#xff0c;有一些细微的差…

    AI如何改变传统工厂的生产模式?

    随着第四次工业革命的浪潮席卷全球&#xff0c;制造业的数字化转型成为企业在竞争中脱颖而出的关键。过去&#xff0c;传统制造业往往依赖于大量的人工操作和低效率的管理流程&#xff0c;而如今&#xff0c;智能化、自动化、数据化已经成为未来制造业的必由之路。从车间到云端…

    Redis

    redis启动命令 默认端口启动redis&#xff1a; redis-server redis.windows.conf 指定端口9001和9002启动redis(需要新建配置文件&#xff0c;并修改配置文件port属性)&#xff1a; redis-server .\redis-9001.conf redis-server .\redis-9002.conf 检查是否启动Redis &#…

    洛谷 P8705:[蓝桥杯 2020 省 B1] 填空题之“试题 E :矩阵” ← 卡特兰数

    【题目来源】 https://www.luogu.com.cn/problem/P8705 【题目描述】 把 1∼2020 放在 21010 的矩阵里。要求同一行中右边的比左边大&#xff0c;同一列中下边的比上边的大。一共有多少种方案? 答案很大&#xff0c;你只需要给出方案数除以 2020 的余数即可。 【答案提交】 …

    ARM 处理器平台 eMMC Flash 存储磨损测试示例

    By Toradex秦海 1). 简介 目前工业嵌入式 ARM 平台最常用的存储器件就是 eMMC Nand Flash 存储&#xff0c;而由于工业设备一般生命周期都比较长&#xff0c;eMMC 存储器件的磨损寿命对于整个设备来说至关重要&#xff0c;因此本文就基于 NXP i.MX8M Mini ARM 处理器平台演示…

    14.二叉搜索树

    二叉搜索树 1.概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树: *若它的左⼦树不为空&#xff0c;则左⼦树上所有结点的值都⼩于等于根结点的值 *若它的右⼦树不为空&#xff0c;则右⼦树上所有结点的值都⼤于等于根结点…

    8、HTTP/1.0和HTTP/1.1的区别【高频】

    第一个是 长连接&#xff1a; HTTP/1.0 默认 短连接&#xff0c;&#xff08;它也可以指定 Connection 首部字段的值为 Keep-Alive实现 长连接&#xff09;而HTTP/1.1 默认支持 长连接&#xff0c;HTTP/1.1是基于 TCP/IP协议的&#xff0c;创建一个TCP连接是需要经过三次握手的…

    【爬虫基础】第二部分 爬虫基础理论 P1/3

    上节内容回顾&#xff1a;【爬虫基础】第一部分 网络通讯 P1/3-CSDN博客 【爬虫基础】第一部分 网络通讯-Socket套接字 P2/3-CSDN博客 【爬虫基础】第一部分 网络通讯-编程 P3/3-CSDN博客 爬虫相关文档&#xff0c;希望互相学习&#xff0c;共同进步 风123456789&#xff…