前言

Rxjava由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎。


今天,我将为大家详细介绍RxJava操作符中最常用的 过滤操作符,希望你们会喜欢。

Carson带你学RxJava系列文章,包括 原理、操作符、应用场景、背压等等,请看文章:Android:这是一份全面 & 详细的RxJava学习指南


目录


1. 作用

过滤 / 筛选 被观察者(Observable)发送的事件 & 观察者 (Observer)接收的事件


2. 类型

  • RxJava2中,过滤操作符的类型包括:

  • 下面,我将对每个操作符进行详细讲解

3. 应用场景 & 对应操作符详解

  • 过滤操作符的应用场景包括:

    1. 根据 指定条件 过滤事件
    2. 根据 指定事件数量 过滤事件
    3. 根据 指定时间 过滤事件
    4. 根据 指定事件位置 过滤事件
  • 下面,我将根据上述应用场景,讲解对应的操作符使用

注:在使用RxJava 2操作符前,记得在项目的Gradle中添加依赖:

dependencies {compile 'io.reactivex.rxjava2:rxandroid:2.0.1'compile 'io.reactivex.rxjava2:rxjava:2.0.7'// 注:RxJava2 与 RxJava1 不能共存,即依赖不能同时存在
}

3.1 根据 指定条件 过滤事件

  • 需求场景
    通过设置指定的过滤条件,当且仅当该事件满足条件,就将该事件过滤(不发送)

  • 对应操作符类型

  • 对应操作符使用

Filter()

  • 作用
    过滤 特定条件的事件

  • 原理

  • 具体使用
Observable.create(new ObservableOnSubscribe<Integer>() {@Overridepublic void subscribe(ObservableEmitter<Integer> emitter) throws Exception {// 1. 发送5个事件emitter.onNext(1);emitter.onNext(2);emitter.onNext(3);emitter.onNext(4);emitter.onNext(5);}// 2. 采用filter()变换操作符}).filter(new Predicate<Integer>() {// 根据test()的返回值 对被观察者发送的事件进行过滤 & 筛选// a. 返回true,则继续发送// b. 返回false,则不发送(即过滤)@Overridepublic boolean test(Integer integer) throws Exception {return integer > 3;// 本例子 = 过滤了整数≤3的事件}}).subscribe(new Observer<Integer>() {@Overridepublic void onSubscribe(Disposable d) {Log.d(TAG, "开始采用subscribe连接");}@Overridepublic void onNext(Integer value) {Log.d(TAG, "过滤后得到的事件是:"+ value  );}@Overridepublic void onError(Throwable e) {Log.d(TAG, "对Error事件作出响应");}@Overridepublic void onComplete() {Log.d(TAG, "对Complete事件作出响应");}});
  • 测试结果

ofType()

  • 作用
    过滤 特定数据类型的数据

  • 具体使用

Observable.just(1, "Carson", 3, "Ho", 5).ofType(Integer.class) // 筛选出 整型数据.subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的整型事件元素是: "+ integer);}});
  • 测试结果

skip() / skipLast()

  • 作用
    跳过某个事件

  • 具体使用

// 使用1:根据顺序跳过数据项Observable.just(1, 2, 3, 4, 5).skip(1) // 跳过正序的前1项.skipLast(2) // 跳过正序的后2项.subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的整型事件元素是: "+ integer);}});// 使用2:根据时间跳过数据项// 发送事件特点:发送数据0-5,每隔1s发送一次,每次递增1;第1次发送延迟0sObservable.intervalRange(0, 5, 0, 1, TimeUnit.SECONDS).skip(1, TimeUnit.SECONDS) // 跳过第1s发送的数据.skipLast(1, TimeUnit.SECONDS) // 跳过最后1s发送的数据.subscribe(new Consumer<Long>() {@Overridepublic void accept( Long along ) throws Exception {Log.d(TAG,"获取到的整型事件元素是: "+ along);}});
  • 测试结果

distinct() / distinctUntilChanged()

  • 作用
    过滤事件序列中重复的事件 / 连续重复的事件

  • 具体使用

// 使用1:过滤事件序列中重复的事件Observable.just(1, 2, 3, 1 , 2 ).distinct().subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"不重复的整型事件元素是: "+ integer);}});// 使用2:过滤事件序列中 连续重复的事件// 下面序列中,连续重复的事件 = 3、4Observable.just(1,2,3,1,2,3,3,4,4 ).distinctUntilChanged().subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"不连续重复的整型事件元素是: "+ integer);}});
  • 测试结果


3.2 根据 指定事件数量 过滤事件

  • 需求场景
    通过设置指定的事件数量,仅发送特定数量的事件

  • 对应操作符类型
    take() & takeLast()

  • 对应操作符使用

take()

  • 作用
    指定观察者最多能接收到的事件数量

  • 原理

  • 具体使用
Observable.create(new ObservableOnSubscribe<Integer>() {@Overridepublic void subscribe(ObservableEmitter<Integer> emitter) throws Exception {// 1. 发送5个事件emitter.onNext(1);emitter.onNext(2);emitter.onNext(3);emitter.onNext(4);emitter.onNext(5);}// 采用take()变换操作符// 指定了观察者只能接收2个事件}).take(2).subscribe(new Observer<Integer>() {@Overridepublic void onSubscribe(Disposable d) {Log.d(TAG, "开始采用subscribe连接");}@Overridepublic void onNext(Integer value) {Log.d(TAG, "过滤后得到的事件是:"+ value  );}@Overridepublic void onError(Throwable e) {Log.d(TAG, "对Error事件作出响应");}@Overridepublic void onComplete() {Log.d(TAG, "对Complete事件作出响应");}});// 实际上,可理解为:被观察者还是发送了5个事件,只是因为操作符的存在拦截了3个事件,最终观察者接收到的是2个事件
  • 测试结果


takeLast()

  • 作用
    指定观察者只能接收到被观察者发送的最后几个事件

  • 具体使用

Observable.just(1, 2, 3, 4, 5).takeLast(3) //指定观察者只能接受被观察者发送的3个事件.subscribe(new Observer<Integer>() {@Overridepublic void onSubscribe(Disposable d) {Log.d(TAG, "开始采用subscribe连接");}@Overridepublic void onNext(Integer value) {Log.d(TAG, "过滤后得到的事件是:"+ value  );}@Overridepublic void onError(Throwable e) {Log.d(TAG, "对Error事件作出响应");}@Overridepublic void onComplete() {Log.d(TAG, "对Complete事件作出响应");}});
  • 测试结果


3.3 根据 指定时间 过滤事件

  • 需求场景
    通过设置指定的时间,仅发送在该时间内的事件

  • 对应操作符类型

  • 对应操作符使用

throttleFirst()/ throttleLast()

  • 作用
    在某段时间内,只发送该段时间内第1次事件 / 最后1次事件

如,1段时间内连续点击按钮,但只执行第1次的点击操作

  • 原理示意图

  • 具体使用
<<- 在某段时间内,只发送该段时间内第1次事件 ->>
Observable.create(new ObservableOnSubscribe<Integer>() {@Overridepublic void subscribe(ObservableEmitter<Integer> e) throws Exception {// 隔段事件发送时间e.onNext(1);Thread.sleep(500);e.onNext(2);Thread.sleep(400);e.onNext(3);Thread.sleep(300);e.onNext(4);Thread.sleep(300);e.onNext(5);Thread.sleep(300);e.onNext(6);Thread.sleep(400);e.onNext(7);Thread.sleep(300);e.onNext(8);Thread.sleep(300);e.onNext(9);Thread.sleep(300);e.onComplete();}}).throttleFirst(1, TimeUnit.SECONDS)//每1秒中采用数据.subscribe(new Observer<Integer>() {@Overridepublic void onSubscribe(Disposable d) {Log.d(TAG, "开始采用subscribe连接");}@Overridepublic void onNext(Integer value) {Log.d(TAG, "接收到了事件"+ value  );}@Overridepublic void onError(Throwable e) {Log.d(TAG, "对Error事件作出响应");}@Overridepublic void onComplete() {Log.d(TAG, "对Complete事件作出响应");}});<<- 在某段时间内,只发送该段时间内最后1次事件 ->>
Observable.create(new ObservableOnSubscribe<Integer>() {@Overridepublic void subscribe(ObservableEmitter<Integer> e) throws Exception {// 隔段事件发送时间e.onNext(1);Thread.sleep(500);e.onNext(2);Thread.sleep(400);e.onNext(3);Thread.sleep(300);e.onNext(4);Thread.sleep(300);e.onNext(5);Thread.sleep(300);e.onNext(6);Thread.sleep(400);e.onNext(7);Thread.sleep(300);e.onNext(8);Thread.sleep(300);e.onNext(9);Thread.sleep(300);e.onComplete();}}).throttleLast(1, TimeUnit.SECONDS)//每1秒中采用数据.subscribe(new Observer<Integer>() {@Overridepublic void onSubscribe(Disposable d) {Log.d(TAG, "开始采用subscribe连接");}@Overridepublic void onNext(Integer value) {Log.d(TAG, "接收到了事件"+ value  );}@Overridepublic void onError(Throwable e) {Log.d(TAG, "对Error事件作出响应");}@Overridepublic void onComplete() {Log.d(TAG, "对Complete事件作出响应");}});
  • 测试结果

Sample()

  • 作用
    在某段时间内,只发送该段时间内最新(最后)1次事件

throttleLast() 操作符类似

  • 具体使用

仅需要把上文的 throttleLast() 改成Sample()操作符即可,此处不作过多描述

throttleWithTimeout () / debounce()

  • 作用
    发送数据事件时,若2次发送事件的间隔<指定时间,就会丢弃前一次的数据,直到指定时间内都没有新数据发射时才会发送后一次的数据

  • 具体使用

Observable.create(new ObservableOnSubscribe<Integer>() {@Overridepublic void subscribe(ObservableEmitter<Integer> e) throws Exception {// 隔段事件发送时间e.onNext(1);Thread.sleep(500);e.onNext(2); // 1和2之间的间隔小于指定时间1s,所以前1次数据(1)会被抛弃,2会被保留Thread.sleep(1500);  // 因为2和3之间的间隔大于指定时间1s,所以之前被保留的2事件将发出e.onNext(3);Thread.sleep(1500);  // 因为3和4之间的间隔大于指定时间1s,所以3事件将发出e.onNext(4);Thread.sleep(500); // 因为4和5之间的间隔小于指定时间1s,所以前1次数据(4)会被抛弃,5会被保留e.onNext(5);Thread.sleep(500); // 因为5和6之间的间隔小于指定时间1s,所以前1次数据(5)会被抛弃,6会被保留e.onNext(6);Thread.sleep(1500); // 因为6和Complete实践之间的间隔大于指定时间1s,所以之前被保留的6事件将发出e.onComplete();}}).throttleWithTimeout(1, TimeUnit.SECONDS)//每1秒中采用数据.subscribe(new Observer<Integer>() {@Overridepublic void onSubscribe(Disposable d) {}@Overridepublic void onNext(Integer value) {Log.d(TAG, "接收到了事件"+ value  );}@Overridepublic void onError(Throwable e) {Log.d(TAG, "对Error事件作出响应");}@Overridepublic void onComplete() {Log.d(TAG, "对Complete事件作出响应");}});
  • 测试结果

3.4 根据 指定事件位置 过滤事件

  • 需求场景
    通过设置指定的位置,过滤在该位置的事件

  • 对应操作符类型

  • 对应操作符使用

firstElement() / lastElement()

  • 作用
    仅选取第1个元素 / 最后一个元素

  • 具体使用

// 获取第1个元素Observable.just(1, 2, 3, 4, 5).firstElement().subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的第一个事件是: "+ integer);}});// 获取最后1个元素Observable.just(1, 2, 3, 4, 5).lastElement().subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的最后1个事件是: "+ integer);}});
  • 测试结果


elementAt()

  • 作用
    指定接收某个元素(通过 索引值 确定)

注:允许越界,即获取的位置索引 > 发送事件序列长度

  • 具体使用
// 使用1:获取位置索引 = 2的 元素// 位置索引从0开始Observable.just(1, 2, 3, 4, 5).elementAt(2).subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的事件元素是: "+ integer);}});// 使用2:获取的位置索引 > 发送事件序列长度时,设置默认参数Observable.just(1, 2, 3, 4, 5).elementAt(6,10).subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的事件元素是: "+ integer);}});
  • 测试结果

elementAtOrError()

  • 作用
    elementAt()的基础上,当出现越界情况(即获取的位置索引 > 发送事件序列长度)时,即抛出异常

  • 具体使用

Observable.just(1, 2, 3, 4, 5).elementAtOrError(6).subscribe(new Consumer<Integer>() {@Overridepublic void accept( Integer integer) throws Exception {Log.d(TAG,"获取到的事件元素是: "+ integer);}});
  • 测试结果

至此,RxJava2中常用的过滤操作符讲解完毕。


4. 实际开发需求案例

  • 在实际开发中,常见的过滤操作符实际需求场景有:功能防抖 & 联想搜索请求优化
  • 下面,我将通过具体实例来讲解上述2个需求

4.1 功能防抖

  • 需求场景

  • 具体使用
    具体请看文章:Android RxJava 实际应用讲解:功能防抖

4.2 联想搜索优化

  • 场景说明

  • 具体使用
    具体请看文章:Android RxJava 实际应用讲解:联想搜索优化

5. Demo地址

上述所有的Demo源代码都存放在:Carson_Ho的Github地址:RxJava2_过滤操作符


6. 总结

  • 下面,我将用一张图总结 RxJava2 中常用的条件 / 布尔操作符

  • Carson带你学RxJava系列文章:

入门
Carson带你学Android:这是一篇清晰易懂的Rxjava入门教程
Carson带你学Android:这是一份面向初学者的RxJava使用指南
Carson带你学Android:RxJava2.0到底更新了什么?(含使用建议)
原理
Carson带你学Android:图文解析RxJava原理
Carson带你学Android:手把手带你源码分析RxJava
使用教程(操作符)
Carson带你学Android:RxJava操作符教程
Carson带你学Android:RxJava创建操作符
Carson带你学Android:RxJava功能性操作符
Carson带你学Android:RxJava过滤操作符
Carson带你学Android:RxJava组合/合并操作符
Carson带你学Android:RxJava变换操作符
Carson带你学Android:RxJava条件/布尔操作符
应用
Carson带你学Android:什么时候应该使用Rxjava?(开发场景汇总)
Carson带你学Android:RxJava线程控制(含实例讲解)
Carson带你学Android:图文详解RxJava背压策略
Carson带你学Android:RxJava、Retrofit联合使用汇总(含实例教程)
Carson带你学Android:优雅实现网络请求嵌套回调
Carson带你学Android:网络请求轮询(有条件)
Carson带你学Android:网络请求轮询(无条件)
Carson带你学Android:网络请求出错重连(结合Retrofit)
Carson带你学Android:合并数据源
Carson带你学Android:联想搜索优化
Carson带你学Android:功能防抖
Carson带你学Android:从磁盘/内存缓存中获取缓存数据
Carson带你学Android:联合判断


欢迎关注Carson_Ho的CSDN博客 与 公众号!

博客链接:https://carsonho.blog.csdn.net/


请帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!

Carson带你学Android:RxJava过滤操作符相关推荐

  1. Carson带你学Android:图文详解RxJava背压策略

    前言 Rxjava,由于其基于事件流的链式调用.逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎. 本文主要讲解的是RxJava中的 背压控制策略,希望你们会喜欢. Cars ...

  2. Carson带你学Android:你要的WebView与 JS 交互方式都在这里了

    前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与 ...

  3. Carson带你学Android:请收好这一份全面详细的Android学习指南

    前言 如果你也学习Android,那么你大概率会看过我的文章.经常有读者给我留言:"该怎么学习Android?"."日常学习Android的方法是什么". 今天 ...

  4. Carson带你学Android:源码解析自定义View Draw过程

    前言 自定义View是Android开发者必须了解的基础 网上有大量关于自定义View原理的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化 等 今天,我将全面总结自定义View ...

  5. Carson带你学Android:这是一份全面详细的属性动画学习攻略!

    前言 属性动画的使用 是 Android 开发中常用的知识 本文将献上一份全面 & 详细的属性动画学习指南,将详细介绍属性动画的所有内容,包括:意义.作用.应用场景.功原理 & 具体使 ...

  6. Carson带你学Android:手把手带你入门跨平台UI开发框架Flutter

    前言 Flutter 作为Google出品的一个新兴的跨平台移动客户端UI开发框架,正在被越来越多的开发者和组织使用,包括阿里的咸鱼.腾讯的微信等. 今天,我将献上一份 <全面 & 详细 ...

  7. Carson带你学Android:全面解析列表ListView与AdapterView

    前言 ListView在Android开发中十分常见 今天,我将为大家带来ListView与AdapterView全面解析,含其特点.工作原理等,希望你们会喜欢. Carson带你学Android系列 ...

  8. Carson带你学Android:这是一份全面详细的WebView学习攻略

    前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 那么这种该如何实现呢?其实这是Android里一个叫WebView组件实现 今天, ...

  9. Carson带你学Android:这是一份全面详细的动画学习指南

    前言 动画的使用 是 Android 开发中常用的知识 可是动画的种类繁多.使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策 本文将献上一份Android动画的全面 ...

最新文章

  1. 27亿参数的「野生版」GPT-3开源,GitHub项目2.9K Star量
  2. CodeForces - 1295D Same GCDs(欧拉函数)
  3. .NET配置文件在写入时损坏
  4. EFI下WIN8.1和Ubuntu的双系统安装
  5. 【设计模式】适配器模式(Adapter Pattern)
  6. Android开发网
  7. pandas去掉html标签,用Pandas清理HTML表
  8. 2月14 大数据处理的基本算法
  9. truffle version/usr/local/lib/node_modules/truffle/build/385.bundled.js:65232 catch cli.bundled.js:6
  10. VSCode 修改界面字体 代码字体 终端字体
  11. Windows anaconda下载安装
  12. css模糊文字,CSS3模糊文字
  13. Chrome浏览器清除cookies方法
  14. 一种新兴计数方式-视觉计数
  15. 用C++写一个简单小病毒(零基础奶妈级教学,不可能学完还不懂)
  16. java项目结局篇之项目进度
  17. foobar2000隐藏桌面悬浮窗头像_如何解锁华为手机隐藏的超能力?
  18. Java简单项目 水果摊
  19. 汽车保养技巧 十大汽车保养技巧
  20. 大豆技术面分析_大豆高产栽培关键技术分析,简单、明了轻松学会

热门文章

  1. python翻译-python实现在线翻译
  2. 关于笔记本WLAN被禁用解决方法
  3. 【JS】购物车附带源码与素材图片压缩包
  4. idea中,maven窗口功能图标含义
  5. 人民大学 环境学院 雷洋(1987-2016)
  6. niagara在linux系统上的安装,TRIDIUM NiagaraAX目录遍历漏洞
  7. Linux中定位JAVAHOME
  8. 8.0.高等数学3-向量的乘法运算(数量积、向量积与混合积)
  9. QT教程,QT从入门到实战教程完整版
  10. ESP32:蓝牙BLE控制M3508电机