RxJava2操作符之flatMap与concatMap

概述

在前文RxJava2操作符之map中记录了map的使用方法及场景,而日常开发中除了map,flatMap以及concatMap使用的也比较多,那这篇文章就记录一下这两个操作符的情况。
RxJava2操作符之map中介绍了一些基础知识以及学习方法,强烈建议先大体浏览一下。

flatMap

使用场景

第一:比较典型的就是可以使用flatMap解决嵌套回调的问题,例如我们有两个API,A和B,B的调用需要A的返回结果作为参数,如果以回调的方式来完成的话,我们需要在A的callback中发起B的调用,然后在B的callback中处理返回结果。
第二:凡是需要map,而变换后需要一个Observable的场景下均可以考虑。

使用说明

官方解释:

Returns an Observable that emits items based on applying a function that you supply to each item emitted by the source ObservableSource, where that function returns an ObservableSource, and then merging those resulting, ObservableSources and emitting the results of this merger.
前半部分与map操作符一致,会对原始发射的每个数据进行转换,但是与map不同的是flatMap对每一个数据项转换后的结果是一个Observable。这些转换后得到的Observable会被合并在一起后由一个统一的Observable分别发射这个集合体的事件。

解释过于抽象,请看下图:
在这里插入图片描述
上面3个圆圈经过中间的flatMap变成了下面的6个菱形。为什么是6个呢,因为图中的flatMap将1个圆圈变成2个菱形。如果faltMap的规则是将1个圆圈变为1个菱形,那么最终就是3个菱形了,这个由我们使用者决定。还有值得注意的一点就是,下面的绿色菱形和蓝色凌的顺序交叉了,而不是按照2个红色,2个绿色,2个蓝色的顺序来的。这说明flatMap变换后发射数据的顺序是不可预测的,这一点要注意。

 Observable.range(1,3)
         .flatMap(new Function<Integer, ObservableSource<String>>()
         {
             @Override
             public ObservableSource<String> apply(final Integer integer) throws Exception
             {
                 return Observable.create(new ObservableOnSubscribe<String>()
                 {
                     @Override
                     public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                         emitter.onNext(String.format("第%s个数据的第1个转换",integer));
                         emitter.onNext(String.format("第%s个数据的第2个转换",integer));
                         emitter.onComplete();
                     }
                 }).subscribeOn(Schedulers.newThread());
             }
         }).subscribeOn(Schedulers.computation())
         .observeOn(AndroidSchedulers.mainThread())
         .subscribe(new Consumer<String>() {
             @Override
             public void accept(String s) throws Exception  {
                 Log.d("FlatMap",s);
             }
         });

上面的代码是将1,2,3三个数据源分别使用flatMap作了变换, 得到3个Observable,而在每一个Observable中又分别发射了两个变换后的数据,那总共就是6条数据。

输出结果:
第一次执行:

2018-10-21 19:06:25.066 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第1个数据的第1个转换
2018-10-21 19:06:25.066 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第2个数据的第1个转换
2018-10-21 19:06:25.066 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第2个数据的第2个转换
2018-10-21 19:06:25.066 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第3个数据的第1个转换
2018-10-21 19:06:25.066 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第3个数据的第2个转换
2018-10-21 19:06:25.066 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第1个数据的第2个转换

第二次执行:

2018-10-21 19:07:15.185 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第3个数据的第1个转换
2018-10-21 19:07:15.186 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第3个数据的第2个转换
2018-10-21 19:07:15.186 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第1个数据的第1个转换
2018-10-21 19:07:15.186 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第1个数据的第2个转换
2018-10-21 19:07:15.186 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第2个数据的第1个转换
2018-10-21 19:07:15.186 8732-8732/top.ss007.rxjavaoperatorsdemo D/FlatMap: 第2个数据的第2个转换

从输出结果可以看到,6个数据项到达观察端的顺序是不固定的,由每个的发射顺序和执行时间一起决定。发射的早而耗时又少的肯定是首先到达,那些发射晚而耗时又长的肯定是最后到达。

那么遇到需要按照发射顺序而获得到达顺序时怎么办呢?conactMap就闪亮登场了!

conactMap

官方解释

Returns a new Observable that emits items resulting from applying a function that you supply to each item emitted by the source ObservableSource, where that function returns an ObservableSource, and then emitting the items that result from concatenating those resulting ObservableSources.

在这里插入图片描述
从上图可知,conactMap 与flatMap唯一的区别就是接收的数据是与发射数据的顺序一致。

将上面代码中的flatMap换为conactMap,然后看一下输出结果:

Observable.range(1,3)
        .concatMap(new Function<Integer, ObservableSource<String>>() {
            ...
        }).subscribeOn(Schedulers.computation())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Consumer<String>()  {
            @Override
            public void accept(String s) throws Exception {
                     Log.d("ConcatMap",s);
            }
        });

输出结果:
第一次输出:

2018-10-21 19:22:13.449 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第1个数据的第1个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第1个数据的第2个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第2个数据的第1个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第2个数据的第2个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第3个数据的第1个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第3个数据的第2个转换

第二次输出:

2018-10-21 19:22:13.449 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第1个数据的第1个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第1个数据的第2个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第2个数据的第1个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第2个数据的第2个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第3个数据的第1个转换
2018-10-21 19:22:13.450 8732-8732/top.ss007.rxjavaoperatorsdemo D/ConcatMap: 第3个数据的第2个转换

可见多次执行后输出结果是稳定的。

总结

Talk is cheap,show me the picture, 真是一图胜前言啊!希望大家再遇到不熟悉的rxjava2的操作符,先看一下那个配图。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShuSheng007

亲爱的猿猿,难道你又要白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值