RxJava操作符系列二(下)

简介:

RxJava操作符系列二

接上文

输出日志信息

 
 
  1. call:2 ConcatMap RxNewThreadScheduler-5 
  2. onNext: ConcatMap 101 ConcatMap 
  3. call:2 ConcatMap RxNewThreadScheduler-6 
  4. onNext: ConcatMap 102 ConcatMap 
  5. call:2 ConcatMap RxNewThreadScheduler-7 
  6. onNext: ConcatMap 103 ConcatMap 
  7. onCompleted: ConcatMap  

通过该操作符和flatMap输出的日志信息,很容易看出flatMap并没有保证数据源的顺序性,但是ConcatMap操作符保证了数据源的顺序性。在应用中,如果你对数据的顺序性有要求的话,就需要使用ConcatMap。若没有要求,二者皆可使用。

SwitchMap

当原始Observable发射一个新的数据(Observable)时,它将取消订阅并停止监视产生执之前那个数据的Observable,只监视当前这一个.

 
 
  1. Integer[] integers = {1, 2, 3}; 
  2. Observable.from(integers).switchMap(new Func1>() { 
  3.             @Override 
  4.             public Observable call(Integer integer) { 
  5.                 Log.e(TAG, "call: SwitchMap" + Thread.currentThread().getName()); 
  6.                 //如果不通过subscribeOn(Schedulers.newThread())在在子线程模拟并发操作,所有数据源依然会全部输出,也就是并发操作此操作符才有作用 
  7.                 //若在此通过Thread。sleep()设置等待时间,则输出信息会不一样。相当于模拟并发程度 
  8.                 return Observable.just((integer + 100) + "SwitchMap").subscribeOn(Schedulers.newThread()); 
  9.             } 
  10.         }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber() { 
  11.             @Override 
  12.             public void onCompleted() { 
  13.                 Log.e(TAG, "onCompleted: SwitchMap"); 
  14.             } 
  15.   
  16.             @Override 
  17.             public void onError(Throwable e) { 
  18.                 Log.e(TAG, "onError: SwitchMap"); 
  19.             } 
  20.   
  21.             @Override 
  22.             public void onNext(String s) { 
  23.                 Log.e(TAG, "onNext: SwitchMap "+s); 
  24.             } 
  25.         });  

输出日志信息

 
 
  1. call: SwitchMapmain 
  2. call: SwitchMapmain 
  3. call: SwitchMapmain 
  4. onNext: SwitchMap 106SwitchMap 
  5. onCompleted: SwitchMap  

当数据源较多时,并不一定是只输出最后一项数据,有可能输出几项数据,也可能是全部。

GroupBy

看到这个词你就应该想到了这个操作符的作用,就是你理解的含义,他将数据源按照你的约定进行分组。我们通过groupBy实行将1到10的数据进行就划分,代码如下

 
 
  1. Observable.range(1, 10).groupBy(new Func1() { 
  2.             @Override 
  3.             public Boolean call(Integer integer) { 
  4.                 return integer % 2 == 0; 
  5.             } 
  6.         }).subscribe(new Subscriber>() { 
  7.             @Override 
  8.             public void onCompleted() { 
  9.                 Log.e(TAG, "onCompleted:1 "); 
  10.             } 
  11.   
  12.             @Override 
  13.             public void onError(Throwable e) { 
  14.                 Log.e(TAG, "onError:1 "); 
  15.             } 
  16.   
  17.             @Override 
  18.             public void onNext(GroupedObservable booleanIntegerGroupedObservable) { 
  19.                 booleanIntegerGroupedObservable.toList().subscribe(new Subscriber>() { 
  20.                     @Override 
  21.                     public void onCompleted() { 
  22.                         Log.e(TAG, "onCompleted:2 " ); 
  23.                     } 
  24.   
  25.                     @Override 
  26.                     public void onError(Throwable e) { 
  27.                         Log.e(TAG, "onError:2 "); 
  28.                     } 
  29.   
  30.                     @Override 
  31.                     public void onNext(List integers) { 
  32.                         Log.e(TAG, "onNext:2 "+integers); 
  33.                     } 
  34.                 }); 
  35.             } 
  36.         });  

输出日志信息

 
 
  1. onNext:2 [1, 3, 5, 7, 9] 
  2. onCompleted:2 
  3. onNext:2 [2, 4, 6, 8, 10] 
  4. onCompleted:2 
  5. onCompleted:1  

在上面代码中booleanIntegerGroupedObservable变量有一个getKey()方法,该方法返回的是分组的key,他的值就是groupBy方法call回调所用函数的值,在上面也就是integer % 2 == 0的值,及true和false。有几个分组也是有此值决定的。

Scan

操作符对原始Observable发射的第一项数据应用一个函数,然后将那个函数的结果作为自己的第一项数据发射。它将函数的结果同第二项数据一起填充给这个函数来产生它自己的第二项数据。它持续进行这个过程来产生剩余的数据序列。

例如计算1+2+3+4的和

 
 
  1. Observable.range(1,4).scan(new Func2() { 
  2.             @Override 
  3.             public Integer call(Integer integerInteger integer2) { 
  4.                 Log.e(TAG, "call: integer:"+integer+"  integer2 "+integer2); 
  5.                 return integer+integer2; 
  6.             } 
  7.         }).subscribe(new Subscriber() { 
  8.             @Override 
  9.             public void onCompleted() { 
  10.                 Log.e(TAG, "onCompleted: "); 
  11.             } 
  12.   
  13.             @Override 
  14.             public void onError(Throwable e) { 
  15.                 Log.e(TAG, "onError: " ); 
  16.             } 
  17.   
  18.             @Override 
  19.             public void onNext(Integer integer) { 
  20.                 Log.e(TAG, "onNext: "+integer ); 
  21.             } 
  22.         });  

输出日志信息

 
 
  1. onNext: 1 
  2. call: integer:1  integer2 2 
  3. onNext: 3 
  4. call: integer:3  integer2 3 
  5. onNext: 6 
  6. call: integer:6  integer2 4 
  7. onNext: 10 
  8. onCompleted:  

对于scan有一个重载方法,可以设置一个初始值,如上面代码,初始值设置为10,只需将scan加个参数scan(10,new Func2)。

Buffer

操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生的Observable发射这些数据的缓存集合,如果原来的Observable发射了一个onError通知,Buffer会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。

示例代码

 
 
  1. Observable.range(10, 6).buffer(2).subscribe(new Subscriber>() { 
  2.             @Override 
  3.             public void onCompleted() { 
  4.                 Log.e(TAG, "onCompleted: "); 
  5.             } 
  6.   
  7.             @Override 
  8.             public void onError(Throwable e) { 
  9.                 Log.e(TAG, "onError: "); 
  10.             } 
  11.   
  12.             @Override 
  13.             public void onNext(List integers) { 
  14.                 Log.e(TAG, "onNext: " + integers); 
  15.             } 
  16.         });  

输出日志信息

 
 
  1. onNext: [10, 11] 
  2. onNext: [12, 13] 
  3. onNext: [14, 15] 
  4. onCompleted:  

上面一次性订阅两个数据,如果设置参数为6,就一次性订阅。buffer的另一重载方法buffer(count, skip)从原始Observable的第一项数据开始创建新的缓存(长度count),此后每当收到skip项数据,用count项数据填充缓存:开头的一项和后续的count-1项,它以列表(List)的形式发射缓存,取决于count和skip的值,这些缓存可能会有重叠部分(比如skip count时)。具体执行结果,你可以设置不同的skip和count观察输出日志,查看执行结果及流程。

Window

Window和Buffer类似,但不是发射来自原始Observable的数据包,它发射的是Observables,这些Observables中的每一个都发射原始Observable数据的一个子集,最后发射一个onCompleted通知。

 
 
  1. Observable.range(10, 6).window(2).subscribe(new Subscriber>() { 
  2.             @Override 
  3.             public void onCompleted() { 
  4.                 Log.e(TAG, "onCompleted1: "); 
  5.             } 
  6.   
  7.             @Override 
  8.             public void onError(Throwable e) { 
  9.                 Log.e(TAG, "onError1: "); 
  10.             } 
  11.   
  12.             @Override 
  13.             public void onNext(Observable integerObservable) { 
  14.                 Log.e(TAG, "onNext1: "); 
  15.                 tv1.append("\n"); 
  16.                 integerObservable.subscribe(new Subscriber() { 
  17.                     @Override 
  18.                     public void onCompleted() { 
  19.                         Log.e(TAG, "onCompleted2: "); 
  20.                     } 
  21.   
  22.                     @Override 
  23.                     public void onError(Throwable e) { 
  24.                         Log.e(TAG, "onError2: "); 
  25.                     } 
  26.   
  27.                     @Override 
  28.                     public void onNext(Integer integer) { 
  29.                         Log.e(TAG, "onNext2: "+integer); 
  30.                     } 
  31.                 }); 
  32.             } 
  33.         });  

输出日志信息

 
 
  1. onNext2: 10 
  2. onNext2: 11 
  3. onCompleted2: 
  4. onNext2: 12 
  5. onNext2: 13 
  6. onCompleted2: 
  7. onNext2: 14 
  8. onNext2: 15 
  9. onCompleted2: 
  10. onCompleted1:  

window和buffer一样也有不同的重载方法。这两个操作符相对其他操作符不太容易理解,可以去RxJava GitHub理解,里面有图示解析。当然最好的理解方式就是通过更改变量的值,去观察输出的日志信息。

好了,这篇文章就介绍到这里。若文中有错误的地方,欢迎指正。谢谢。





本文作者:佚名
来源:51CTO
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
开发工具 iOS开发 MacOS
解决VScode文件无法编辑(删除键 换行键失去作用)
解决VScode文件无法编辑(删除键 换行键失去作用)
2571 0
|
前端开发 Android开发 容器
surfaceview组件的surfaceCreated()不被调用的解决方案
原文:surfaceview组件的surfaceCreated()不被调用的解决方案 有时候我们有需要在native层做在surfaceview的上下文中做渲染,这个时候只是提供了一个单独什么都不做的surfaceview。
3415 0
|
10月前
|
存储 Java Android开发
关于安卓bugly更新,bugly上传符号表实现
关于安卓bugly更新,bugly上传符号表实现
293 0
|
存储 消息中间件 Kubernetes
10分钟在 Rainbond 上部署 mall 电商项目
本文介绍在 Rainbond 上的两种部署 mall 电商项目的方式: 1. 通过 Rainbond 开源应用商店快速部署 mall 2. 从 0 开始部署 mall 项目所有服务
|
前端开发 Java Android开发
打造 Compose 版本的 Banner
打造 Compose 版本的 Banner
236 0
打造 Compose 版本的 Banner
|
Java Android开发
Android反编译:使用dex2jar查看dex文件
Android反编译:使用dex2jar查看dex文件
441 0
|
XML JSON Java
Jetpack 系列之Paging3,看这一篇就够了~
Jetpack 系列之Paging3,看这一篇就够了~
2999 4
Jetpack 系列之Paging3,看这一篇就够了~
|
存储 对象存储
【阿里云OSS】You have no right to access this object because of bucket acl.
【阿里云OSS】You have no right to access this object because of bucket acl.
4520 0
【阿里云OSS】You have no right to access this object because of bucket acl.
|
11月前
|
小程序 程序员 API
小程序(uniapp)上传头像至OSS(阿里云)--保姆级
前言 自微信小程序改版以来,现在获取用户的头像和昵称就不能直接通过wx.getUserInfo获取了。而是需要用户主动在登录后填写自己的昵称和头像,微信只是提供一个一键填写的快捷操作让用户直接使用自己已有的微信昵称或头像。
2526 0
|
XML 存储 前端开发
如何用 Jetpack Compose 开发一个页面?
本文简单介绍了下如何使用 Compose 开发一个简单的页面,这里面包含了一些基本的要素:定义组件、更新状态、预览页面。有关 Compose 的架构,以及它的渲染原理,可以期待以后的文章。
278 0
如何用 Jetpack Compose 开发一个页面?