rxjava2代码实战3--flatMap,concatMap操作符

flatMap,concatMap

flatMap操作符可以将一个Observable转换为另一个Observable发射出去,并且可以将多个事件转化为1个,但是最后输出的事件序列顺序是不确定的,如果想要最后输出的事件顺序和源数据的顺序一致只要换成concatMap就可以了。
flatMap和Map操作符的不同是map一次只能转换一个事件。

代码地址:
GodisGod/Rxjava2Test
https://github.com/GodisGod/Rxjava2Test

代码实战:

根据学生的成绩输出对老师的描述

                Observable.create(new ObservableOnSubscribe<Student>() {
                    @Override
                    public void subscribe(ObservableEmitter<Student> e) throws Exception {
                        List<Student> students = new ArrayList<Student>();
                        students.add(new Student("LHD1", 60));
                        students.add(new Student("LHD2", 70));
                        for (Student s : students) {
                            e.onNext(s);//发送多个事件
                        }
                    }
                })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .flatMap(new Function<Student, ObservableSource<Integer>>() {
                            @Override
                            public ObservableSource<Integer> apply(Student student) throws Exception {
                                List<Integer> lists = new ArrayList<>();
                                lists.add(student.getMath());
                                lists.add(student.getEnglish());
                                lists.add(student.getChinese());//将每个事件又分成多个事件
                                return Observable.fromIterable(lists).delay(10, TimeUnit.NANOSECONDS);//将这些事件合并成一个Observable
                            }
                        })
                        .subscribe(new Consumer<Integer>() {
                            @Override
                            public void accept(Integer integers) throws Exception {
                                Log.i("LHD", "成绩: " + integers.toString());
                            }
                        });

上面的代码中一共发出了5个学生事件,然后我们将每一个学生的成绩又分成三个事件,最后将成绩合并为一个Observable将成绩列表发射出去。

结果:
flatmap
每点击一次按钮就会发送两个学生的成绩,前两次点击都会按照顺序发送,第三次点击的时候,发现两个人的成绩事件交叉在了一起,而不是先发完送一个人的再发送另一个人的,这说明flatmap的事件发送是无序的。
具体请看源码哦(#^.^#)

附上一张flatmap的流程图:
flatmap
其中圆形可以看成每一个学生事件,三角形和正方形则可以看成是每个学生的成绩事件。最后的事件流向,可以发现两个学生的成绩是无序的。

flatMap可以连续多次调用

代码示例:

                Observable.create(new ObservableOnSubscribe<List<Student>>() {
                    @Override
                    public void subscribe(ObservableEmitter<List<Student>> e) throws Exception {
                        List<Student> students = new ArrayList<Student>();
                        students.add(new Student("LHD1", 60));
                        students.add(new Student("LHD2", 70));
                        students.add(new Student("LHD3", 80));
                        students.add(new Student("LHD4", 90));
                        students.add(new Student("LHD5", 100));
                        e.onNext(students);
                    }
                })
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .flatMap(new Function<List<Student>, ObservableSource<Teacher>>() {
                            @Override
                            public ObservableSource<Teacher> apply(List<Student> students) throws Exception {
                                Teacher teacher = new Teacher();
                                teacher.setName("笨老师");
                                teacher.setGood(false);
                                for (Student s : students) {
                                    if (s.getScore() > 90) {
                                        teacher.setName("好老师");
                                        teacher.setGood(true);
                                    }
                                }
                                return Observable.just(teacher);
                            }
                        })
                        .flatMap(new Function<Teacher, ObservableSource<String>>() {
                            @Override
                            public ObservableSource<String> apply(Teacher teacher) throws Exception {
                                String str = "这个 " + teacher.getName() + " good 不?";
                                return Observable.just(str);
                            }
                        })
                        .subscribe(new Consumer<String>() {
                            @Override
                            public void accept(String string) throws Exception {
                                Log.i("LHD", string);
                                tvResult.setText(string);
                            }
                        });

上面的代码我们使用了两次flatMap,第一次将5个学生事件转变为1个老师事件,第二次将老师事件转化为一个字符串,最后将这个字符串发射出去。

flatMap转换后的数据是无序的

代码示例:

 Observable.create(new ObservableOnSubscribe<Student>() {
                    @Override
                    public void subscribe(ObservableEmitter<Student> e) throws Exception {
                        e.onNext(new Student("第一名", 100));
                        e.onNext(new Student("第二名", 90));
                        e.onNext(new Student("第三名", 80));
                    }
                }).subscribeOn(Schedulers.io())
                        .flatMap(new Function<Student, ObservableSource<String>>() {
                            @Override
                            public ObservableSource<String> apply(Student student) throws Exception {
                                final String str = "老师正在教导" + student.getName() + ",她考了" + student.getScore() + "分";
                                Log.i("LHD1", str);//在这里检测事件的转换顺序
                                int delay = 100;
                                if (student.getScore() == 100) {
                                    delay = 500;
                                }
                                return Observable.just(str).delay(delay, TimeUnit.MILLISECONDS);
                            }
                        })
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Consumer<String>() {
                            @Override
                            public void accept(String s) throws Exception {
                                tvResult.append(s + "\n");
                                Log.i("LHD2", s + "\n");//在这里检测事件的接受顺序
                            }
                        });

为了能观察到事件是无序的,我们把第一个事件的学生成绩设置为100,然后在flatMap里判断当学生的成绩为100的时候我们延时500ms再发射事件。

结果:

flatmap

可以发现我们转换事件的顺序是和数据源相同的但是发射事件的顺序果然变得无序了。
本来应该是100,90,80结果在接收端变成了90,80,100

concatmap
可以发现事件顺序是:
LHD1—100 发射端
LHD1—90 发射端
LHD2—100
LHD1—80 发射端

LHD2—90
LHD2—80
可以看到使用concatMap转换后的事件仍然是有序的

以上就是flatMap和concatMap的简单介绍啦。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值