【Rxjava详解】(二) 操作符的妙用

文章目录

    • 接口变化
    • 操作符
      • map
      • flatmap
      • debounce
      • throttleFirst()
      • take
      • concat

RxJava 是一个基于 观察者模式的异步编程库,它提供了丰富的操作符来处理和转换数据流。 操作符是 RxJava 的核心组成部分,它们提供了一种灵活、可组合的方式来处理数据流,使得开发者可以更加便捷地进行数据处理和流程控制。

接口变化

RxJava 2.x拥有了新的特性,其依赖于4个接口:

  • Publisher
  • Subscriber
  • Subscription
  • Processor
  1. SubscriberFunc1变为Function等等。此外,还引入了SingleMaybeCompletable等新的可观察类型。
  2. RxJava 2.x 中的背压支持:RxJava 2.x 引入了对背压的支持,新增了Flowable类型来处理背压场景。同时,对一些操作符的行为进行了一些修改以适应背压机制。
  3. 异常处理方式的变化:在RxJava 1.x中,异常处理是通过onError()方法来处理,而在RxJava 2.x中,引入了onError(Throwable)方法和onError(Throwable, boolean)方法,允许开发者控制是否中断流程。
  4. 取消订阅的方式变化:在RxJava 1.x中,使用unsubscribe()方法取消订阅,而在RxJava 2.x中,使用dispose()方法取消订阅

关于背压:

在RxJava中,背压(Backpressure)是一种处理生产者和消费者之间速度不匹配的机制。通过背压,可以使得消费者根据自身的处理能力告知生产者它们能够接受的数据量,从而避免生产者产生过多的数据导致消费者无法处理的情况。

而在RxJava 2.x ~ RxJava 3.x,发生以下变化:

  • 不再支持Backpressure:RxJava 3.x不再内置支持背压机制,而是采用基于Reactive-Streams的响应式规范,并提供了相应的Flowable类型。因此,在RxJava 3.x中,需要使用Flowable来处理背压场景。
  • Observer接口的变化:在RxJava 3.x中,Observer接口被拆分为两个接口:ObserverDisposableObserver接口用于处理事件的消费,而Disposable接口用于取消订阅。
  • SingleObserverCompletableObserver的变化:在RxJava 3.x中,SingleObserverCompletableObserver接口的方法签名有所变化,取消订阅的方法从dispose()改为了onDispose()

操作符

RxJava提供了对事件序列进行变换的支持,这是它的核心功能之一.所谓变换,就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
操作符是用来对Observable(或Flowable)流进行转换、过滤、组合和操作的方法。

RxJava提供了很多很有用的操作符。多的要死
在Rxjava 3.x 下,有以下常见的操作符:

  1. map:将Observable发射的数据项通过指定的函数进行转换,并发射转换后的数据项。
  2. filter:根据指定的条件过滤Observable发射的数据项,只发射满足条件的数据项。
  3. take:只发射Observable发射的前N个数据项,忽略后面的数据项。
  4. skip:跳过Observable发射的前N个数据项,只发射后面的数据项。
  5. merge:将多个Observable合并成一个Observable,按照时间顺序发射合并后的数据项。
  6. zip:将多个Observable按照顺序进行合并,每个数据项都是由对应位置的Observable发射的数据项组合而成。
  7. concat:按照顺序连接多个Observable,依次发射它们的数据项,等前一个Observable完成后才会订阅下一个Observable。
  8. onErrorResumeNext:在Observable发生错误时,使用备用的Observable继续发射数据项。
  9. retry:在Observable发生错误时,进行错误重试,重新订阅Observable。
  10. interval:创建一个按照固定时间间隔发射递增数值的Observable。
  11. debounce:只有在指定的时间间隔内没有发射新的数据项时,才发射最后一个数据项。
  12. distinct:过滤掉重复的数据项,只发射不重复的数据项。
  13. flatMap:将Observable发射的数据项转换为Observable集合,并按顺序发射这些Observable发射的数据项。
  14. reduce:对Observable发射的数据项进行累积操作,返回最终的累积结果。
  15. scan:对Observable发射的数据项进行累积操作,并按顺序发射每次累积的结果

在此简单介绍其中几个的用法:

map

示意图:

image.png

实际上,map操作符可以理解为对Observable发射的每个数据项都应用一个函数,将原始数据项转换为另一种形式的数据项,然后再发射出去。(感觉Kotlin里有)

假设我们有一个Observable发射的是整数序列,我们想将每个整数乘以2,并发射出去。

Observable<Integer> observable = Observable.just(1, 2, 3, 4, 5);observable.map(number -> number * 2).subscribe(result -> System.out.println(result));输出:
2
4
6
8
10

flatmap

flatMap操作符会对Observable的每个数据项应用一个函数,这个函数返回一个新的Observable。然后,它会将这些新的Observable合并成一个Observable,并发射合并后的数据项。

假设我们有一个Observable发射的是字符串数组,我们想将每个字符串拆分为字符数组,并发射出去。

Observable<String> observable = Observable.just("Hello", "World", "RxJava");observable.flatMap(str -> Observable.fromArray(str.split(""))).subscribe(character -> System.out.print(character + " "));

输出:

H e l l o W o r l d R x J a v a

flatMap操作符将每个字符串拆分为字符数组,并将所有的字符合并成了一个Observable,最终发射出去。

debounce

debounce操作符也是RxJava中常用的操作符之一,它用于在一定时间间隔内只发射最后一个数据项,忽略中间的数据项。debounce操作符主要用于处理需要在一定时间内连续发生的事件,但只关心最后一个事件的场景。

在安卓开发中,debounce操作符可以用于处理用户输入场景,比如搜索框输入关键词时,通常需要等待用户停止输入一段时间后再进行搜索,以减少不必要的网络请求。

Observable<String> observable = Observable.create(emitter -> {editText.addTextChangedListener(new TextWatcher() {@Overridepublic void beforeTextChanged(CharSequence s, int start, int count, int after) {}@Overridepublic void onTextChanged(CharSequence s, int start, int before, int count) {}@Overridepublic void afterTextChanged(Editable s) {emitter.onNext(s.toString());}});
});observable.debounce(500, TimeUnit.MILLISECONDS).subscribe(keyword -> {// 进行搜索操作performSearch(keyword);});

我们首先创建了一个Observable对象,该Observable通过监听EditText的文本变化事件,将用户输入的关键词发射出去。

然后,我们使用debounce操作符,设置一个时间间隔(这里是500毫秒),它会在用户输入停止500毫秒后才发射最后一个关键词。

最后,通过subscribe方法订阅Observable,并在订阅中执行搜索操作。

这样做的好处是,用户在连续输入时,debounce操作符会忽略中间的输入,只关注最后一个输入,在用户停止输入一段时间后才执行搜索操作,避免不必要的网络请求。

throttleFirst()

throttleFirst()操作符也是RxJava中常用的操作符之一,它用于在指定时间间隔内只发射第一个数据项,忽略后续的数据项。throttleFirst操作符主要用于处理需要限制触发频率的事件,保证在指定时间间隔内只处理一次。

在安卓开发中,throttleFirst操作符可以用于处理按钮点击事件,防止用户重复点击按钮造成重复操作:

Observable<Object> observable = Observable.create(emitter -> {button.setOnClickListener(v -> {emitter.onNext(new Object());});
});observable.throttleFirst(1000, TimeUnit.MILLISECONDS).subscribe(event -> {// 执行按钮点击操作ClickAction();});

take

take()操作符也是RxJava中常用的操作符之一,用于从Observable中取出一定数量的数据项,并在达到指定数量后停止发射。它可以与Retrofit和RxJava的线程切换一起使用,来控制网络请求结果的数量和线程切换。

在安卓开发中,通常使用Retrofit进行网络请求,而结合RxJava可以实现异步操作和线程切换。下面是一个结合Retrofit和RxJava的实例,使用take操作符来限制结果数量,并配合线程切换:

首先,创建一个网络请求的接口:

public interface ApiInterface {@GET("data")Observable<List<Data>> getData();
}

然后,创建一个Retrofit实例,并结合RxJava的Observable进行网络请求:

ApiInterface apiInterface = RetrofitClient.getClient().create(ApiInterface.class);apiInterface.getData().subscribeOn(Schedulers.io()) // 在IO线程进行网络请求.observeOn(AndroidSchedulers.mainThread()) // 在主线程接收和处理结果.take(5) // 只接收前5个数据项.subscribe(dataList -> {// 处理获取到的数据for (Data data : dataList) {Log.d(TAG, "Received data: " + data.toString());}}, throwable -> {// 处理错误Log.e(TAG, "Error: " + throwable.getMessage());});

先建了一个ApiInterface的实例,用于定义网络接口。

然后用Retrofit和RxJava的Observable结合进行网络请求。通过subscribeOn()方法指定在IO线程进行网络请求,observeOn()方法指定在主线程接收和处理结果。使用take(5)操作符来限制只接收前5个数据项,即结果数量限制为5。

最后,通过subscribe方法订阅Observable,并在订阅中处理获取到的数据或错误。

concat

concat()操作符是RxJava中常用的操作符之一,用于将多个Observable按顺序连接在一起,并依次发射数据。它可以在安卓开发中用于实现多个下载任务的顺序执行。

在安卓开发中,有时需要进行多个文件的下载操作,可以使用concat操作符来依次执行下载任务:

创建一个下载任务的接口:

public interface DownloadService {@GETObservable<ResponseBody> downloadFile(@Url String fileUrl);
}

Retrofit结合RxJava的Observable进行下载任务:

DownloadService service = RetrofitClient.getClient().create(DownloadService.class);Observable<ResponseBody> downloadTask1 = service.downloadFile("http://example.com/file1");
Observable<ResponseBody> downloadTask2 = service.downloadFile("http://example.com/file2");
Observable<ResponseBody> downloadTask3 = service.downloadFile("http://example.com/file3");Observable.concat(downloadTask1, downloadTask2, downloadTask3).subscribeOn(Schedulers.io()) // 在IO线程进行下载任务.observeOn(AndroidSchedulers.mainThread()) // 在主线程接收和处理结果.subscribe(responseBody -> {// 处理下载完成的文件saveFile(responseBody);}, throwable -> {// 处理错误Log.e(TAG, "Error: " + throwable.getMessage());});

操作符真的很多,其他的可以看详细文档进行转换,学习RxJava的操作符的关键是理解其原理和使用场景,以及熟悉常用的操作符和它们的功能。

操作符可以总结为以下几种:

  1. 转换操作符:用来对数据进行转换,比如将一个数据类型转换成另一个数据类型,或者对数据进行映射或扁平化处理。
  2. 过滤操作符:用来过滤数据流中的元素,比如只保留满足特定条件的元素,或者去除重复的元素。
  3. 组合操作符:用来将多个数据流进行组合,比如将多个流依次连接在一起,或者合并多个流的元素。
  4. 错误处理操作符:用来处理异常和错误情况,比如在遇到错误时返回一个默认值,或者在错误发生时切换到另一个数据流。
  5. 调度操作符:用来控制数据流在不同线程之间的切换,比如将数据流切换到IO线程执行耗时操作,或者将结果切换回主线程更新UI。

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

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

相关文章

【如何学习Python自动化测试】—— 多层窗口定位

6 、 多层窗口定位 多层窗口指的是在操作系统图形界面中&#xff0c;一个窗口被另一个窗口覆盖的情况。在多层窗口中&#xff0c;如何定位需要操作的窗口&#xff1f; 一种常见的方法是使用操作系统提供的AltTab快捷键&#xff0c;可以在打开的所有窗口中快速切换焦点。如果需要…

20231122给RK3399的挖掘机开发板适配Android12

20231122给RK3399的挖掘机开发板适配Android12 2023/11/22 9:30 主要步骤&#xff1a; rootrootrootroot-X99-Turbo:~$ tar --use-compress-programpigz -xvpf rk356x_android12_220722.tgz rootrootrootroot-X99-Turbo:~$ cd rk_android12_220722/ rootrootrootroot-X99-Tur…

带记忆的超级GPT智能体,能做饭、煮咖啡、整理家务!

随着AI技术的快速迭代&#xff0c;Alexa、Siri、小度、天猫精灵等语音助手得到了广泛应用。但在自然语言理解和完成复杂任务方面仍然有限。 相比文本的标准格式&#xff0c;语音充满复杂性和多样性&#xff08;例如&#xff0c;地方话&#xff09;,传统方法很难适应不同用户的…

【每日OJ —— 20.有效的括号(栈)】

每日OJ —— 20.有效的括号&#xff08;栈&#xff09; 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09;2.方法讲解2.1.解法2.1.1.算法讲解2.1.2.代码实现2.1.3.提交通过展示 1.题目&#xff1a;20.有效的括号&#xff08;栈&#xff09; 2.方法讲解 2.1.解法 利用…

2023 年 亚太赛 APMCM (B题)国际大学生数学建模挑战赛 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 问题一&#xff1a; 建立没有作物的玻璃温室内的温度和风速分…

MacOS 成为恶意软件活动的目标

Malwarebytes 警告称&#xff0c;一个针对 Mac 操作系统 (OS) 的数据窃取程序正在通过虚假的网络浏览器更新分发给毫无戒心的目标。 Atomic Stealer&#xff0c;也称为 AMOS&#xff0c;是 Mac OS 上流行的窃取程序。 Atomic Stealer (AMOS) 恶意软件最近被发现使用“ClearFa…

ImportError: cannot import name ‘contextfilter‘ from ‘jinja2‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

汇编-pop出栈指令

32位汇编 执行动作分为两步&#xff1a; 第一步&#xff1a;读出数据 第二步&#xff1a;改变栈地址 如果操作数是16位&#xff0c; 则ESP加2&#xff1b; 如果操作数是32位&#xff0c; 则ESP加4 espesp2 或 espesp4 格式&#xff1a;

IDEA中 java: 警告: 源发行版 11 需要目标发行版 11 如何解决

步骤1找到项目结构&#xff0c;下面有两种方式 步骤2找到 模块中对应的项目&#xff0c;修改对应的源的语言级别和依赖的模块SDK(M) 步骤3&#xff0c;启动一下&#xff0c;看有无问题&#xff0c; 步骤4&#xff0c;去文件-->设置-->构建、执行、部署-->编译器-->…

中职组网络安全B模块-渗透提权2

任务五&#xff1a;渗透提权2 任务环境说明&#xff1a; 仅能获取xxx的IP地址 用户名&#xff1a;test&#xff0c;密码&#xff1a;123456 访问服务器主机&#xff0c;找到主机中管理员名称&#xff0c;将管理员名称作为Flag值提交&#xff1b; Flag:doyoudoyoudo 访问服…

感恩三十载 再创新辉煌——中国音乐著作权协会成立30周年暨著作权集体管理制度实施30周年纪念大会在京召开

感恩三十载 再创新辉煌 2023年11月19日&#xff0c;中国音乐著作权协会成立30周年暨著作权集体管理制度实施30周年纪念大会在北京举行。中宣部副部长张建春&#xff0c;国际作者和作曲者协会联合会&#xff08;CISAC&#xff09;总干事甘迪奥龙&#xff08;Gadi Oron&#xff0…

深入了解批处理文件:从基础到实例

1. 什么是批处理文件&#xff1f; 批处理文件是一种包含一系列命令的文本文件&#xff0c;通常用于自动化执行一系列任务。在不同操作系统中&#xff0c;批处理也有不同的名称&#xff0c;如在Windows中被称为批处理文件&#xff08;.bat&#xff09;&#xff0c;而在Linux中则…

1、基础入门——操作系统文件下载反弹SHELL防火墙绕过

名词解释 POC&#xff1a;验证漏洞存在的代码&#xff1b; EXP&#xff1a;利用漏洞的代码&#xff1b; payload&#xff1a;漏洞利用载荷&#xff0c; shellcode&#xff1a;漏洞代码&#xff0c; webshell&#xff1a;特指网站后门&#xff1b; 木马&#xff1a;强调控制…

Day40:139.单词拆分、背包问题总结

文章目录 139.单词拆分思路代码实现 背包问题总结背包类型递推公式 139.单词拆分 题目链接 思路 确定dp数组以及下标的含义 dp[i] : 从0开始长度为i的字符串是否可以拆分为一个或多个在字典中出现的单词确定递推公式 如果确定dp[j] 是true&#xff0c;且 [j, i] 这个区间的子…

关于ElectronVue3中集成讯飞星火AI

前言&#xff1a;我的最终目的是为了在QQ上集成一个AI机器人&#xff0c;因此在这里先实现一个简单的集成 先上效果图 总体还是很简单的&#xff0c;我在调用websock获取回复内容的基础上另外集成了一个事件总线&#xff0c;让我们在调用获取消息的时候能够更加方便快捷 工具代…

联想拯救者Lenovo Legion R9000K 2021H(82N6)原装出厂Windows10/Win11系统ISO镜像

链接&#xff1a;https://pan.baidu.com/s/13NkeCXNdV0Ib5eeRnZUeAQ?pwdnlr7 提取码&#xff1a;nlr7 拯救者笔记本电脑原厂WIN系统自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文…

启发式搜索算法-人工智能

第1关:评估函数和启发信息 第2关:A*搜索算法 class Array2D:"""说明:1.构造方法需要两个参数,即二维数组的 宽和高2.成员变量w和h是二维数组的宽和高3.使用:‘对象[x][y]’可以直接取到相应的值4.数组的默认值都是0"""def __init__(s…

使用PySpark 结合Apache SystemDS 进行信号处理分析 (离散傅立叶变换)的简单例子

文章大纲 简介 :什么是 SystemDS ?环境搭建与数据 准备数据预处理模型训练 与 结果评估参考文献简介 :什么是 SystemDS ? SystemDS is an open source ML system for the end-to-end data science lifecycle from data integration, cleaning, and feature engineering, ov…

干货分享丨客户旅程管理的框架与案例

融合焕新&#xff0c;数字化转型打造客户经营新旅程。本文围绕该主题详细描述了客户旅程管理的框架&#xff0c;并通过实践案例进一步验证客户旅程管理的价值。 以下内容根据行业知名企业专家刘胜强的分享整理&#xff0c;完整版内容请点击文末“阅读原文”观看哦~ 一、客户时代…

【libGDX】使用Mesh绘制矩形

1 前言 使用Mesh绘制三角形 中介绍了绘制三角形的方法&#xff0c;本文将介绍绘制正方形的方法。 libGDX 以点、线段、三角形为图元&#xff0c;没有提供绘制矩形内部的接口。要绘制矩形内部&#xff0c;必须通过三角形拼接而成&#xff0c;如下图&#xff0c;是通过GL_TRIANGL…