前言:
本篇基於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 版權聲明:本文爲博主原創文章,轉載請附上博文連接!