1. 程式人生 > >RxJava(四) concatMap操作符用法詳解

RxJava(四) concatMap操作符用法詳解

RxJava系列文章目錄導讀:

concatMap操作符的作用

concatMap操作符和flatMap操作符非常類似。如果對 flatMap操作符 不是很瞭解可以點選連結去看看我的上一篇博文。下面是concatMap操作符的流程圖:

concatMap和flatMap最大的區別是concatMap發射的資料集是有序的,flatMap發射的資料集是無序的。

concatMap操作符的用法示例

通過上一篇對flatMap的介紹,我們的例子程式輸出的結果是無序的。現在把程式碼中的flatMap換成concatMap:

Observable.from(Arrays.asList(
            "http://www.baidu.com/"
, "http://www.google.com/", "https://www.bing.com/")) .concatMap(new Func1<String, Observable<String>>() { @Override public Observable<String> call(String s) { return createIpObservableMultiThread(s); } }) .observeOn(AndroidSchedulers.mainThread()); // 獲取ip
private synchronized Observable<String> createIpObservableMultiThread(final String url) { return Observable .create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { try
{ String ip = getIPByUrl(url); printLog(tvLogs, "Emit Data -> ", url + "->" + ip); subscriber.onNext(ip); } catch (MalformedURLException e) { e.printStackTrace(); //subscriber.onError(e); subscriber.onNext(null); } catch (UnknownHostException e) { e.printStackTrace(); //subscriber.onError(e); subscriber.onNext(null); } subscriber.onCompleted(); } }) .subscribeOn(Schedulers.io()); }

輸出結果:

Emit Data -> 'http://www.baidu.com/->115.239.211.112' , Main Thread:false, Thread Name:RxCachedThreadScheduler-1
Consume Data <- '115.239.211.112' , Main Thread:true, Thread Name:main
Emit Data -> 'http://www.google.com/->216.58.221.132'Main Thread:false, Thread Name:RxCachedThreadScheduler-3
Emit Data -> 'https://www.bing.com/->202.89.233.104' Main Thread:false, Thread Name:RxCachedThreadScheduler-2
Consume Data <- '216.58.221.132' Main Thread:true, Thread Name:main
Consume Data <- '202.89.233.104' Main Thread:true, Thread Name:main 

輸出的結果始終都是baidu/google/bing, 使用的執行緒都是不同的執行緒。這也就解決了上篇部落格提出的問題:既要是多個執行緒完成任務,又要保持任務的順序

但是出現了一個奇怪的問題:上篇部落格我們使用flatMap在多個執行緒完成任務,有時候順序是亂的。但是concatMap一開始也是使用一個執行緒來完成任務,只有先呼叫flatMap多執行緒完成任務,然後再呼叫concatMap才會有多執行緒。
實驗結果表明:如果RxJava有了多個執行緒,concatMap才會使用多個執行緒,如果Rxjava裡只有一個快取的執行緒,concatMap只是用一個執行緒來執行任務,儘管加上了.subscribeOn(Schedulers.io())程式碼。然而如果是flatMap加上.subscribeOn(Schedulers.io())程式碼,每次呼叫都是多個執行緒的。這也是flatMap和concatMap的又一個區別。