前言:
本篇基于Map操做符,阅读该篇请确保,你已经了解过它:RxJava2 转换操做符之Map()方法。一如既往,干大事的人都是直接先上图,再解释的。(建议用PC端阅读,图片能够放大。排版,也有利于阅读)java
2、FlatMap的操做流程图解
先来跟你讲讲,这图咋看。这上面的线,表示原始数据。下面的线,表示转换后的数据。中间的块,表明转换过程。两条线的结尾有一小条竖线,表示结束。箭头的方向,从左到右,表示运行过程,是从左到右跑的。
一、(Question-1)你可能会奇怪,为毛从左到右数,第5个会是绿色的,不该该也是蓝色的吗?
这个,得分红多步解释,请耐心一下:git
圆与棱形是一对多的关系。即一个圆既能够转换成一个棱形,也能够转换成多个棱形。该图解,以每1个圆都对应2个棱形为例。那么,可不能够第1个圆对应2个棱形,第2个圆对应3个棱形,第3个圆对应x个棱形呢?固然能够!
FlatMap的Flat是铺平的意思。即先将全部圆转成棱形,好比例子中,是先将3个圆转成6个棱形。而后,再一 一开始对它们进行转换,看图(… 找个时间得学一下ps才行, 图有点粗糙,但理不糙):
虽然,是从左到右开始执行任务。但谁先执行完,谁就先返回。就跟跑步同样,虽然有人先跑,但未必他就是先到终点的。
圆是一级任务,每个一级任务包含多个二级子任务。子任务,便是棱形。
二、(Question-2)不是说,一个一个执行吗?那怎么会出现交叉(就是两蓝中插了个一绿的)呢?
由于,不一样的二级任务的执行时间是不一样的。比方说:第一个绿色棱形的任务是计算:1+1。第二个绿色的棱形任务是:从服务器获取用户信息和系统配置。第一个蓝色棱形的任务是计算:2+2。第二个蓝色的棱形任务是:作特别复杂耗时的操做,比第二个绿色的棱形的任务执行的还要久。那么,从例子能够看出。第一个绿色棱形确定是先完成。但第二个绿色棱形的任务,执行的时间确定比,第一个蓝色棱形的任务还要久。因此,就会出现,先出现第一个蓝色棱形,后再出现第二个绿色的棱形。。。github
3、少跟我说理论!上代码,要复制就能跑,一眼就看得懂的。
答:… 先喝点加多宝,我这就上代码。服务器
public static void actionFlatMap() {app
List<Integer> list = Arrays.asList(1, 2, 3);ui
// 这里用了lambda。
Observable.fromIterable(list)
.flatMap(integer -> {
log("开始执行,第" + integer + "圆球的任务" + getThreadName());
return getObservable(integer);
}).subscribe(s -> log("已完成" + s + getThreadName()));.net
}线程
public static Observable<String> getObservable(final int integer) {
return Observable.create((ObservableOnSubscribe<String>) emitter -> {
emitter.onNext("第" + integer + "圆球的第1个棱形任务");
if(integer != 1) {
// 第2和第3个圆球的第二个任务延时。
Thread.sleep(5 * 1000);
}
emitter.onNext("第" + integer + "圆球的第2个棱形任务");
emitter.onComplete();
}).subscribeOn(Schedulers.newThread());
}翻译
// 返回当前的线程名
public static String getThreadName() {
return " | ThreadName=" + Thread.currentThread().getName();
}orm
private static void log(String log) {
Log.d("FlatMap", log);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
这是运行结果:
D/TransformingOperations: 开始执行,第1圆球的任务 | ThreadName=main
D/TransformingOperations: 开始执行,第2圆球的任务 | ThreadName=main
D/TransformingOperations: 开始执行,第3圆球的任务 | ThreadName=main
D/TransformingOperations: 已完成第2圆球的第1个棱形任务 | ThreadName=RxNewThreadScheduler-2
D/TransformingOperations: 已完成第3圆球的第1个棱形任务 | ThreadName=RxNewThreadScheduler-3
D/TransformingOperations: 已完成第1圆球的第1个棱形任务 | ThreadName=RxNewThreadScheduler-3
D/TransformingOperations: 已完成第1圆球的第2个棱形任务 | ThreadName=RxNewThreadScheduler-3
D/TransformingOperations: 已完成第2圆球的第2个棱形任务 | ThreadName=RxNewThreadScheduler-2
D/TransformingOperations: 已完成第3圆球的第2个棱形任务 | ThreadName=RxNewThreadScheduler-2
1
2
3
4
5
6
7
8
9
从打印的结果能够看到,FlatMap,首先是从1到3,即从左到右,执行任务的。其中,一、二、3又各自包含2个子任务。虽然是从1到3开始执行。可是,很明显,未必就是1先执行完毕。反而是,二、3的第一个任务先完成,而后,才是1的两个任务完成。而后,才是二、3的两个被延时处理的任务被分别完成。从这个例子,咱们得出这样一个结论:FlatMap执行流程是:先将全部一级任务,铺平成全部二级任务。再依照,从左到右到执行次序,执行任务。可是,任务成功的回调,却不是从左到右的。而是,谁先完成谁先回调。简言之,即:执行次序是必定的,完成次序是不肯定的。
4、让咱们来看看Rx官方是怎么解释的
FlatMap,英文水平有限,若是翻译有不当之处,欢迎各类建议。
一、transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable。
翻译过来就是:由一个Observable发射一组任务,来将它们转成多个Observable。而后,铺平那些Observable到一个Observable里面。听起来是否是很难理解?由于这是硬翻译,来看看软翻译怎么说:
由一个Observable来触发执行,一组转换任务。作法是:先将这些任务以及它们的子任务,提出来。而后,再将这些任务合并到一个Observable里面。最后,由这个Observable,对这些任务进行遍历处理。。。若是还看不懂,不要紧,下面还有更详细的解释。
二、The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items. FlatMap then merges the emissions of these resulting Observables, emitting these merged results as its own sequence.
This method is useful, for example, when you have an Observable that emits a series of items that themselves have Observable members or are in other ways transformable into Observables, so that you can create a new Observable that emits the complete collection of items emitted by the sub-Observables of these items.
Note that FlatMap merges the emissions of these Observables, so that they may interleave.
In several of the language-specific implementations there is also an operator that does not interleave the emissions from the transformed Observables, but instead emits these emissions in strict order, often called ConcatMap or something similar.
FlatMap操做符,转换一个Observable的作法是,对每个任务,都经过调用SourceObservable的方法来实现转换。这个方法由你实现,具体的转换逻辑,就在这个方法里面处理。而且,该方法会返回一个Observable,这个Observable又能够处理它本身的任务。FlatMap会合并全部的任务,即将一级任务,先所有转成二级任务,再遍历处理。
这个方法是颇有用的。好比说,当你的Observable执行一组任务,或处理一组数据的同时。这些任务或数据,又包含有本身的任务,或数据。因此,你能够为每个任务,建立一个Observable来处理,它们的二级任务。
注意:由于FlatMap会合并全部的任务。因此,它们可能会有交叉现象。。这句话的意思是,由于将全部一级任务的二级任务都合并成一条线。而后,遍历执行。这样,有的任务,可能会因耗时而慢回调。从而致使,先执行,后回调的现象。
最后一段,简而言之:若是,你既想实现这个功能,又不想出现交叉。即每个任务,都会等前一个任务,执行完,再回调。能够用ConcatMap操做符。下篇,咱们会讲:ConcatMap操做符和FlatMapIterable操做符。
到此为止,FlatMap操做符的讲解,已经所有说完了。若是,你还有什么迷惑不解,能够在评论区指出。
附上能够跑的代码(0 warnings, 0 errors):
https://github.com/SuperBeagleDog/OkMVP
注意:
这个库里面有不少东西,RxJava2的转换操做符部分的demo位于:com.lyf.okmvp.demo.rxjava2包下的TransformingOperations类里面。
用法:
一、直接在com.lyf.okmvp.ui包下的MainActivity类里的onCreate()方法里面,直接调用:
TransformingOperations.actionFlatMap(); // 静态方法。
二、也能够复制TransformingOperations类到你的项目里,去随心所欲。但前提时,你得有配置过RxJava和RxAndroid。配置方法,自行百度,或参考个人OkMVP库。 --------------------- 做者:岳锋 来源:CSDN 原文:https://blog.csdn.net/l_o_s/article/details/79412300 版权声明:本文为博主原创文章,转载请附上博文连接!