Rxjava操作符之变换操作符

前言

本文基于Rxjava2,与Rxjava略有不同

1,map()
  • 描述:对原始Observable发射的每一项数据应用一个你选择的函数,然后返回一个发射这些结果的Observable

  • 官方示意图:

  • 示例:

        Observable.just(1, 2, 3, 4, 5)
                .map(new Function<Integer, String>() {
                    @Override
                    public String apply(Integer integer) throws Exception {
                        return "第" + integer + "变";
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.i(TAG, "onSubscribe");
                    }

                    @Override
                    public void onNext(String value) {
                        Log.i(TAG, "onNext,value:" + value);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i(TAG, "onError");
                    }

                    @Override
                    public void onComplete() {
                        Log.i(TAG, "onComplete");
                    }
                });
  • 输出:

2,flatMap()
  • 描述:使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap的作用就是合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。

  • 官方示意图:

  • 注意:此合并操作是无序的,即不保证合并后发射的顺序与原始顺序相同。如要保证顺序选择使用concatMap()。如果任何一个通过这个flatMap操作产生的单独的Observable调用onError异常终止了,这个Observable自身会立即调用onError并终止

  • 示例:

        Observable.just(1, 2, 3, 4)
                .flatMap(new Function<Integer, ObservableSource<String>>() {
                    @Override
                    public ObservableSource<String> apply(Integer integer) throws Exception {
                        //这里把每个事件拆分成三个子事件,一一进行发送
                        List<String> list = new ArrayList<>();
                        for (int i1 = 0; i1 < 3; i1++) {
                            list.add("第" + integer + "个事件的第" + i1 + "个子事件");
                        }
                        return Observable.fromIterable(list);
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.i(TAG,"onSubscribe");
                    }

                    @Override
                    public void onNext(String s) {
                        Log.i(TAG,"onNext,value:"+s);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i(TAG,"onError");
                    }

                    @Override
                    public void onComplete() {
                        Log.i(TAG,"onComplete");
                    }
                });
  • 输出:

  • 重载:

    • flatMap(Func1,int):第二个参数设置flatMap从原来的Observable映射Observables的最大同时订阅数。当达到这个限制时,它会等待其中一个终止然后再订阅另一个

    • flatMap(Func1,Func1,Func0):为原始Observable的每一项数据和每一个通知创建一个新的Observable(并对数据平坦化)

    • flatMap(Func1,Func1,Func0,int):同上,增加最大同时订阅数

  • 应用:此操作符与concatMap一样通常用作数据平坦化。例如:有一个学生类集合,每个学生有各个科目的成绩,需求是打印每个学生的各科成绩。通常我们是如此实现:

        List<StudentBean> students = new ArrayList<>();
        //...省略添加学生数据
        Observable.fromIterable(students)
                .subscribe(new Consumer<StudentBean>() {
                    @Override
                    public void accept(StudentBean studentBean) throws Exception {
                        List<StudentBean.Subject> grades = studentBean.getGrade();
                        for (int i1 = 0; i1 < grades.size(); i1++) {
                            Log.i(TAG, "name:" + grades.get(i1).getSubjectName() + "score:" + grades.get(i1).getScore());
                        }
                    }
                });

这样可以实现,但是如果我不想在观察者中使用for循环,而是直接传入Subject成绩对象怎么办呢?这一点很重要,因为后续有可能需要对每个Subject对象进行操作。这时候flatMap()的数据平坦化作用就体现出来了。改造如下:

        List<StudentBean> students = new ArrayList<>();
        //...省略添加学生数据
        Observable.fromIterable(students)
                .flatMap(new Function<StudentBean, ObservableSource<StudentBean.Subject>>() {
                    @Override
                    public ObservableSource<StudentBean.Subject> apply(StudentBean studentBean) throws Exception {
                        return Observable.fromIterable(studentBean.getGrade());
                    }
                })
                .subscribe(new Consumer<StudentBean.Subject>() {
                    @Override
                    public void accept(StudentBean.Subject subject) throws Exception {
                        Log.i(TAG, "name:" + subject.getSubjectName() + "score:" + subject.getScore());
                    }
                });

很优美对不对?此外,我们可以使用flatMap()来中进行嵌套异步操作,或者嵌套的网络访问,一条链走到底。

3,flatMapIterable()
  • 描述:flatMapIterableflatMap在处理方式上相同的。唯一不同的是,flatMap是把一个Observable转换成多个Observables。每一个Observable,最后需要返回一个Observable。而flatMapIterable在将一个Observable转换成多个Observables后,每一个Observable只能返回一个Iterable,而不是Observable。(Iterable是个接口,Collection实现了此接口,也就是所有的list、set都是它的子类)

  • 官方示意图:

  • 示例:

        Observable.just(1, 2, 3)
                .flatMapIterable(new Function<Integer, Iterable<String>>() {
                    @Override
                    public Iterable<String> apply(Integer integer) throws Exception {
                        return Arrays.asList("第一个元素" + integer, "第二个元素" + integer);
                    }
                })
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.i(TAG, "accept:" + s);
                    }
                });
  • 输出:

  • 重载:flatMapIterable(Func1,Func2)

4,concatMap()
  • 描述:它类似于最简单版本的flatMap,但是它按次序连接而不是合并那些生成的Observables,然后产生自己的数据序列。与flatMap用法一模一样。

  • 官方示意图:

5,switchMap()
  • 描述:它和flatMap很像,除了一点:当原始Observable发射一个新的数据(Observable)时,它将取消订阅并停止监视产生这之前那个数据的Observable,只监视当前这一个。如果是在同一线程中,第二个数据项来临时第一个已经完成了,此操作符不会产生效果。当在多线程中,第二个数据项来临后如果第一个没有完成,将会取消订阅并停止监视前一个Observable

  • 官方示意图:

  • 示例:

            Observable.just(1, 2, 3)
                .switchMap(new Function<Integer, ObservableSource<String>>() {
                    @Override
                    public ObservableSource<String> apply(Integer integer) throws Exception {
                        List<String> list = new ArrayList<>();
                        for (int i1 = 0; i1 < 2; i1++) {
                            list.add("第" + integer + "个事件的第" + i1 + "个子事件");
                        }
                        //多线程中订阅
                        return Observable.fromIterable(list).subscribeOn(Schedulers.newThread());
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.i(TAG, "onSubscribe");
                    }

                    @Override
                    public void onNext(String s) {
                        Log.i(TAG, "onNext,value:" + s);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i(TAG, "onError");
                    }

                    @Override
                    public void onComplete() {
                        Log.i(TAG, "onComplete");
                    }
                });
  • 输出:

    没有第一个和第二个事件,是因为都被后一个事件来临后给取消了。

6,split()
  • 描述:在特殊的StringObservable类(默认没有包含在RxJava中)中还有一个split操作符。它将一个发射字符串的Observable转换为另一个发射字符串的Observable,只不过,后者将原始的数据序列当做一个数据流,使用一个正则表达式边界分割它们,然后合并发射分割的结果。

  • 官方示意图:

7,buffer()
  • 描述:将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生的Observable发射这些数据的缓存集合。

  • 注意:如果原来的Observable发射了一个onError通知,Buffer会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。

  • 官方示意图:

  • 示例:

        Observable.just(1, 2, 3, 4, 5)
                .buffer(2)
                .subscribe(new Observer<List<Integer>>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.i(TAG, "onSubscribe");
                    }

                    @Override
                    public void onNext(List<Integer> integers) {
                        Log.i(TAG, "onNext:缓存集合长度:" + integers.size());
                        for (int i1 = 0; i1 < integers.size(); i1++) {
                            Log.i(TAG, "onNext:集合item:" + integers.get(i1));
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i(TAG, "onError");
                    }

                    @Override
                    public void onComplete() {
                        Log.i(TAG, "onComplete");
                    }
                });
  • 输出:

  • 重载:

    • buffer(count, skip)

      • 描述:从原始Observable的第一项数据开始创建新的缓存,此后每当收到skip项数据,用count项数据填充缓存:开头的一项和后续的count-1项,它以列表(List)的形式发射缓存,取决于countskip的值,这些缓存可能会有重叠部分(比如skip < count时),也可能会有间隙(比如skip > count时)。

      • 示意图:

    • buffer(bufferClosingSelector)

      • 描述:当它订阅原来的Observable时,buffer(bufferClosingSelector)开始将数据收集到一个List,然后它调用bufferClosingSelector生成第二个Observable,当第二个Observable发射一个TClosing时,buffer发射当前的List,然后重复这个过程:开始组装一个新的List,然后调用bufferClosingSelector创建一个新的Observable并监视它。它会一直这样做直到原来的Observable执行完成。

      • 示意图:

    • buffer(boundary)

      • 描述:buffer(boundary)监视一个名叫boundaryObservable,每当这个Observable发射了一个值,它就创建一个新的List开始收集来自原始Observable的数据并发射原来的List

      • 示意图:

    • buffer(bufferOpenings, bufferClosingSelector)

      • 描述:buffer(bufferOpenings, bufferClosingSelector)监视这个叫bufferOpeningsObservable(它发射BufferOpening对象),每当bufferOpenings发射了一个数据时,它就创建一个新的List开始收集原始Observable的数据,并将bufferOpenings传递给closingSelector函数。这个函数返回一个Observablebuffer监视这个Observable,当它检测到一个来自这个Observable的数据时,就关闭List并且发射它自己的数据(之前的那个List)。

      • 示意图:

    • buffer(timespan, unit[, scheduler])

      • 描述:buffer(timespan, unit)定期以List的形式发射新的数据,每个时间段,收集来自原始Observable的数据(从前面一个数据包裹之后,或者如果是第一个数据包裹,从有观察者订阅原来的Observale之后开始)。还有另一个版本的buffer接受一个Scheduler参数,默认情况下会使用computation调度器。

      • 示意图:

    • buffer(timespan, unit, count[, scheduler])

      • 描述:每当收到来自原始Observablecount项数据,或者每过了一段指定的时间后,buffer(timespan, unit, count)就以List的形式发射这期间的数据,即使数据项少于count项。还有另一个版本的buffer接受一个Scheduler参数,默认情况下会使用computation调度器。

      • 示意图:

    • buffer(timespan, timeshift, unit[, scheduler])

      • 描述:buffer(timespan, timeshift, unit)在每一个timeshift时期内都创建一个新的List,然后用原始Observable发射的每一项数据填充这个列表(在把这个List当做自己的数据发射前,从创建时开始,直到过了timespan这么长的时间)。如果timespan长于timeshift,它发射的数据包将会重叠,因此可能包含重复的数据项。

      • 示意图:

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

  • 示意图:

  • 示例:

    Observable.just(1, 2, 3, 4, 5)
        .scan(new Func2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer sum, Integer item) {
                return sum + item;
            }
        }).subscribe(new Subscriber<Integer>() {
            @Override
            public void onNext(Integer item) {
                System.out.println("Next: " + item);
            }

            @Override
            public void onError(Throwable error) {
                System.err.println("Error: " + error.getMessage());
            }

            @Override
            public void onCompleted() {
                System.out.println("Sequence complete.");
            }
        });
  • 输出:

    Next: 1
    Next: 3
    Next: 6
    Next: 10
    Next: 15
    Sequence complete.
    
  • 重载:

    • scan(R,Func2)
    • 说明:你可以传递一个种子值给累加器函数的第一次调用(Observable发射的第一项数据)。如果你使用这个操作符,scan将发射种子值作为自己的第一项数据。注意:传递null作为种子值与不传递是不同的,null种子值是合法的。

其他操作符介绍:

Rxjava操作符之创建操作符

Rxjava操作符之结合类操作符

Rxjava操作符之过滤操作

Rxjava操作符之辅助操作

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值