Android RxJava操作符详解系列: 变换操作符

原创 2017年10月23日 09:24:11

前言

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

Github截图

如果还不了解 RxJava,请看文章:Android:这是一篇 清晰 & 易懂的Rxjava 入门教程


  • RxJava如此受欢迎的原因,在于其提供了丰富 & 功能强大的操作符,几乎能完成所有的功能需求
  • 今天,我将为大家详细介绍RxJava操作符中最常用的变换操作符,并附带 Retrofit 结合 RxJava的实例Demo教学,希望你们会喜欢。

  1. 本系列文章主要基于 Rxjava 2.0
  2. 接下来的时间,我将持续推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!

  3. 示意图

目录

示意图


1. 作用

  • 对事件序列中的事件 / 整个事件序列 进行加工处理(即变换),使得其转变成不同的事件 / 整个事件序列
  • 具体原理如下

示意图


2. 类型

  • RxJava中常见的变换操作符如下:
    示意图

  • 下面,我将对每种操作符进行详细介绍

    注:本文只讲解RxJava2在开发过程中常用的变换操作符


3. 应用场景 & 对应操作符 介绍

  • 下面,我将对 RxJava2 中的变换操作符进行逐个讲解
  • 注:在使用RxJava 2操作符前,记得在项目的Gradle中添加依赖:
dependencies {
      compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
      compile 'io.reactivex.rxjava2:rxjava:2.0.7'
      // 注:RxJava2 与 RxJava1 不能共存,即依赖不能同时存在
}

3.1 Map()

  • 作用
    对 被观察者发送的每1个事件都通过 指定的函数 处理,从而变换成另外一种事件

    即, 将被观察者发送的事件转换为任意的类型事件。

  • 原理

示意图

  • 应用场景
    数据类型转换

  • 具体使用
    下面以将 使用Map() 将事件的参数从 整型 变换成 字符串类型 为例子说明

示意图

 // 采用RxJava基于事件流的链式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {

            // 1. 被观察者发送事件 = 参数为整型 = 1、2、3
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);

            }
            // 2. 使用Map变换操作符中的Function函数对被观察者发送的事件进行统一变换:整型变换成字符串类型
        }).map(new Function<Integer, String>() {
            @Override
            public String apply(Integer integer) throws Exception {
                return "使用 Map变换操作符 将事件" + integer +"的参数从 整型"+integer + " 变换成 字符串类型" + integer ;
            }
        }).subscribe(new Consumer<String>() {

            // 3. 观察者接收事件时,是接收到变换后的事件 = 字符串类型
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, s);
            }
        });
  • 测试结果

示意图

从上面可以看出,map() 将参数中的 Integer 类型对象转换成一个 String类型 对象后返回

同时,事件的参数类型也由 Integer 类型变成了 String 类型


3.2 FlatMap()

  • 作用:将被观察者发送的事件序列进行 拆分 & 单独转换,再合并成一个新的事件序列,最后再进行发送

  • 原理

    1. 为事件序列中每个事件都创建一个 Observable 对象;
    2. 将对每个 原始事件 转换后的 新事件 都放入到对应 Observable对象;
    3. 将新建的每个Observable 都合并到一个 新建的、总的Observable 对象;
    4. 新建的、总的Observable 对象 将 新合并的事件序列 发送给观察者(Observer

示意图

  • 应用场景
    无序的将被观察者发送的整个事件序列进行变换

  • 具体使用

// 采用RxJava基于事件流的链式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
            }

            // 采用flatMap()变换操作符
        }).flatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer integer) throws Exception {
                final List<String> list = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    list.add("我是事件 " + integer + "拆分后的子事件" + i);
                    // 通过flatMap中将被观察者生产的事件序列先进行拆分,再将每个事件转换为一个新的发送三个String事件
                    // 最终合并,再发送给被观察者
                }
                return Observable.fromIterable(list);
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, s);
            }
        });
  • 测试结果
    示意图
    注:新合并生成的事件序列顺序是无序的,即 与旧序列发送事件的顺序无关

3.3 ConcatMap()

  • 作用:类似FlatMap()操作符
  • FlatMap()的 区别在于:拆分 & 重新合并生成的事件序列 的顺序 = 被观察者旧序列生产的顺序

  • 原理

示意图

  • 应用场景
    有序的将被观察者发送的整个事件序列进行变换

  • 具体使用

// 采用RxJava基于事件流的链式操作
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
                emitter.onNext(1);
                emitter.onNext(2);
                emitter.onNext(3);
            }

            // 采用concatMap()变换操作符
        }).concatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            public ObservableSource<String> apply(Integer integer) throws Exception {
                final List<String> list = new ArrayList<>();
                for (int i = 0; i < 3; i++) {
                    list.add("我是事件 " + integer + "拆分后的子事件" + i);
                    // 通过concatMap中将被观察者生产的事件序列先进行拆分,再将每个事件转换为一个新的发送三个String事件
                    // 最终合并,再发送给被观察者
                }
                return Observable.fromIterable(list);
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d(TAG, s);
            }
        });
  • 测试结果
    示意图

注:新合并生成的事件序列顺序是有序的,即 严格按照旧序列发送事件的顺序


3.4 Buffer()

  • 作用
    定期从 被观察者(Obervable)需要发送的事件中 获取一定数量的事件 & 放到缓存区中,最终发送

  • 原理

示意图

  • 应用场景
    缓存被观察者发送的事件

  • 具体使用
    那么,Buffer()每次是获取多少个事件放到缓存区中的呢?下面我将通过一个例子来说明

// 被观察者 需要发送5个数字
        Observable.just(1, 2, 3, 4, 5)
                .buffer(3, 1) // 设置缓存区大小 & 步长
                                    // 缓存区大小 = 每次从被观察者中获取的事件数量
                                    // 步长 = 每次获取新事件的数量
                .subscribe(new Observer<List<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }
                    @Override
                    public void onNext(List<Integer> stringList) {
                        //
                        Log.d(TAG, " 缓存区里的事件数量 = " +  stringList.size());
                        for (Integer value : stringList) {
                            Log.d(TAG, " 事件 = " + value);
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d(TAG, "对Error事件作出响应" );
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "对Complete事件作出响应");
                    }
                });
  • 测试结果

示意图

  • 过程解释

下面,我将通过一个图来解释Buffer()原理 & 整个例子的结果
示意图

至此,关于RxJava2中主要的变换操作符已经讲解完毕


4. 实际开发需求案例


5. Demo地址

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

喜欢的麻烦点个star


6. 总结

  • 下面,我将用一张图总结 RxJava2 中常用的变换操作符

示意图

  • 接下来的时间,我将持续推出 AndroidRxjava 2.0 的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!

示意图


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

版权声明:本文为博主原创文章,未经博主允许不得转载,更多文章请继续关注Carson_Ho的博客!

相关文章推荐

RxJava系列之二 变换类操作符详解1

1.回顾上一篇文章我们主要介绍了RxJava , RxJava 的Observables和 RxJava的just操作符。以及RxJava一些常用的操作。 没看过的抓紧点我去看吧。 其实R...
  • jys1115
  • jys1115
  • 2015年08月24日 16:07
  • 1744

【Android】Rxjava操作符系列(二)

今天天气不错啊,继续撸操作符!1.debounce作用:debounce操作符是对源Observable间隔期产生的结果进行过滤,如果在这个规定的间隔期内没有别的结果产生,则将这个结果提交给订阅者,否...

RxJava系列(二、详解操作符)

RxJava中的操作符(Operators),RxJava中的操作符主要分成了三类: 转换类操作符、过滤类操作符、组合类操作符转换类操作符 Map map()函数接受一个Func1类型的参数,然后...

Android RxJava操作符详解 系列:组合 / 合并操作符

前言 Rxjava,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎。 如果还不了解 RxJava,请看文章:Android:这是一篇 清晰 & 易懂的...

Android RxJava操作符详解系列: 创建操作符

转自--------http://blog.csdn.net/carson_ho/article/details/78246732 前言 Rxjava,由于其基于事件流的链式调...

RxJava操作符系列二

RxJava操作符源码传送门 在上篇文章RxJava操作符系列一我们介绍的操作符几乎都是创建被观察者的操作符,那么今天的这篇文章就介绍一下经常用到的转换操作符。话不多说,开始上车。 Map ...

RxJava操作符系列四

RxJava操作符系列传送门RxJava操作符源码 RxJava操作符系列一 RxJava操作符系列二 RxJava操作符系列三 前言在上一篇文章我们主要介绍的是RxJava的一些...

RxJava入门系列二,操作符篇

RxJava入门系列二,操作符篇在RxJava入门系列一基础篇中,我介绍了RxJava的基础框架,同时也介绍了map()操作符的使用.然而我知道你现在对RxJava的了解还不够深入,所以你不能让自己去...

RxJava2的do系列操作符之doOnNext和doFinally

1.doOnNext 它产生的Observable每发射一项数据就会调用它一次,但是它的Action不是接受一个Notification参数,而是接受发射的数据项。Observable.just(1...

RxJava系列5(组合操作符)

作者:张磊(BaronZhang) 链接:https://zhuanlan.zhihu.com/p/22039934 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android RxJava操作符详解系列: 变换操作符
举报原因:
原因补充:

(最多只允许输入30个字)