【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.hqwc.cn/news/208299.html

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

相关文章

在AWS VPC中运行Nagios检查时指定自定义DNS解析器的选项

在AWS VPC中运行Nagios检查&#xff0c;并希望能够指定自定义DNS解析器来处理请求。我想使用Python requests库来实现这个目标。 根据问题描述&#xff0c;您想在AWS VPC中运行Nagios检查&#xff0c;并希望使用Python的requests库来指定自定义DNS解析器。 要解决这个问题&…

Dubbo从入门到上天系列第十八篇:Dubbo引入注册中心简介以及DubboAdmin简要介绍,为后续详解Dubbo各种注册中心做铺垫!

一&#xff1a;Dubbo注册中心引言 1&#xff1a;什么是Dubbo的注册中心&#xff1f; Dubbo注册中心是Dubbo服务治理中极其重要的一个概念。它主要是用于对Rpc集群应用实例进行管理。 对于我们的Dubbo服务来讲&#xff0c;至少有两部分构成&#xff0c;一部分是Provider一部分是…

spark shuffle 剖析

ShuffleExchangeExec private lazy val writeMetrics SQLShuffleWriteMetricsReporter.createShuffleWriteMetrics(sparkContext)private[sql] lazy val readMetrics SQLShuffleReadMetricsReporter.createShuffleReadMetrics(sparkContext)用在了两个地方&#xff0c;承接的是…

利用 Apache Ranger 管理 Amazon EMR 中的数据权限

需求背景简介 系统安全通常包括两个核心主题&#xff1a;身份验证和授权。一个解决“用户是谁”的问题&#xff0c;另一个解决“用户允许执行什么操作”的问题。在大数据领域&#xff0c;Apache Ranger 是最受欢迎的授权选择之一&#xff0c;它支持所有主流大数据组件&#xff…

filebeat配置解析【待续】

目录 filebeat概览filebeat是如何工作的工作原理采集日志注册表发送日志 容器日志采集的三种方式方式一&#xff1a;Filebeat 与 应用运行在同一容器&#xff08;不推荐&#xff09;方式二&#xff1a;Filebeat 与 应用运行不在同一容器方式三&#xff1a;通过 Kubernetes File…

网络渗透测试(wireshark 抓取QQ图片)

1.打开wireshark 这里我用的wifi连接 所以点开wifi就好 打开wifi之后就开始在本机上进行抓包了 我们先给我们的QQ发送一张图片&#xff0c;用自己的手机发送给电脑 然后点击左上角的正方形&#xff0c;停止捕获抓包 QQ的关键词是oicq&#xff0c;所以我们直接找 打开oicq …

Kubernetes+Gitlab+Jenkins+ArgoCD多集群部署

KubernetesGitlabJenkinsArgoCD多集群部署 文章目录 KubernetesGitlabJenkinsArgoCD多集群部署1. KubernetesGitlabJenkinsArgoCD多集群部署2. 添加WebHooks自动触发3. Jenkins-构建-执行Shell4. 制作镜像及修改Yaml文件4.1 Dockerfile4.2 Build-Shell 5.自动部署Demo测试5.1 推…

CSM32RV003:国产高精度16位ADC低功耗RISC-V内核MCU

目录 高精度ADC工业应用工业数据采集应用CSM32RV003简介主要特性 高精度ADC工业应用 高精度ADC即高精度模数转换器&#xff0c;是一种能够将输入模拟信号转换为数字信号的芯片&#xff0c;在多种消费电子、工业、医疗和科研领域都有广泛应用。高精度ADC的主要特点是能够提供高…

飞桨——总结PPOCRLabel中遇到的坑

操作系统&#xff1a;win10 python环境&#xff1a;python3.9 paddleocr项目版本&#xff1a;2.7 1.报错&#xff1a;ModuleNotFoundError: No module named Polygon&#xff08;已解决&#xff09; 已解决所以没有复现报错内容 尝试方法一&#xff1a;直接使用pip命令安装&…

VR全景:赋能城市园区建设,打造3DVR城市名片

近年来&#xff0c;很多城市都在大力发展数字化经济建设&#xff0c;以VR全景技术赋能现代化城市和园区建设&#xff0c;为城市园区展示带来了全新的可能性。借助3D、VR技术把现实城市和园区搬到互联网上进行全方位展示&#xff0c;将城市园区的形象、景观、规划布局等1&#x…

深度学习常见激活函数:ReLU,sigmoid,Tanh,softmax,Leaky ReLU,PReLU,ELU整理集合,应用场景选择

文章目录 1、ReLU 函数&#xff08;隐藏层中是一个常用的默认选择&#xff09;1.1 优点1.2 缺点 2、sigmoid 函数2.1 优点2.2 缺点 3、Tanh 函数3.1 优点3.2 缺点 4、softmax 函数&#xff08;多分类任务最后一层都会使用&#xff09;5、Leaky ReLU 函数5.1 优点5.2 缺点 6、PR…

java--飞翔的小鸟

游戏玩法&#xff1a;通过鼠标点击使小鸟上下移动穿过柱子并完成得分&#xff0c;小鸟碰到柱子或掉落到地面上都会结束游戏。 游戏内图片 Brid类&#xff1a; package bird;import org.omg.CORBA.IMP_LIMIT;import javax.imageio.ImageIO; import java.awt.image.BufferedIma…