看完不懂Rxjava我跪搓板(1)

0. 為了月薪1.8萬

奮斗方向和目標(biāo).png

1. 什么是函數(shù)式編程

  • 函數(shù)式編程是一種編程范式霞捡,是面向數(shù)學(xué)的抽象,將計(jì)算描述為一種表達(dá)式求值充岛,函數(shù)可以在任何地方定義泄隔,并且可以對函數(shù)進(jìn)行組合拒贱。體現(xiàn)在RxJava上很明顯的就是鏈?zhǔn)讲僮鳌⒉僮鞣膽?yīng)用佛嬉。

2. 什么是響應(yīng)式編程

  • 響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式逻澳,數(shù)據(jù)更新是相關(guān)聯(lián)的。舉一個(gè)簡單的例子:A = B + C ,A被賦值為B和C的值,緊接著B發(fā)生了變化暖呕,但是A卻不會發(fā)生變化赡盘。但如果是響應(yīng)式編程缰揪,當(dāng)B發(fā)生變化以后陨享,A就會隨之發(fā)生改變。體現(xiàn)在RxJava上很明顯的就是我們對數(shù)據(jù)流的操作以及當(dāng)被觀察者發(fā)生變化的時(shí)候钝腺,觀察者隨之發(fā)生變化抛姑。

3. 什么是函數(shù)響應(yīng)式編程

  • 把函數(shù)式編程里面的一套思路和響應(yīng)式編程合起來就是函數(shù)響應(yīng)式編程。它可以極大地簡化項(xiàng)目艳狐,特別是處理嵌套回調(diào)的異步事件定硝、復(fù)雜的列表過濾和變換或者時(shí)間相關(guān)問題。

4. RxJava概述

  • RxJava是一個(gè)函數(shù)庫毫目,讓開發(fā)者可以利用可觀察序列和LINQ風(fēng)格查詢操作符來編寫異步和基于事件的程序蔬啡。
  • 開發(fā)者可以用Observables表示異步數(shù)據(jù)流诲侮,用LINQ操作符查詢異步數(shù)據(jù)流,用Schedulers參數(shù)化異步數(shù)據(jù)流的并發(fā)處理箱蟆。
  • Rx可以這樣定義:Rx = Observables + LINQ + Schedulers.

5. 為何要用RxJava

  • 代碼簡潔:異步操作有Handler沟绪、AsyncTask等,但是使用RxJava空猜,就算再多的異步操作绽慈,代碼邏輯越來越復(fù)雜,RxJava依然可以保持清晰的邏輯辈毯。

  • 舉例:假設(shè)有這樣一個(gè)需求:界面上有一個(gè)自定義的視圖 imageCollectorView 坝疼,它的作用是顯示多張圖片,并能使用 addImage(Bitmap) 方法來任意增加顯示的圖片∽晃郑現(xiàn)在需要程序?qū)⒁粋€(gè)給出的目錄數(shù)組 File[] folders 中每個(gè)目錄下的 png 圖片都加載出來并顯示在 imageCollectorView 中钝凶。需要注意的是,由于讀取圖片的這一過程較為耗時(shí)唁影,需要放在后臺執(zhí)行腿椎,而圖片的顯示則必須在 UI 線程執(zhí)行。我們分別展示非RxJava的操作和RxJava的操作夭咬。

非RxJava:

new Thread() {
    @Override
    public void run() {
        super.run();
        for (File folder : folders) {
            File[] files = folder.listFiles();
            for (File file : files) {
                if (file.getName().endsWith(".png")) {
                    final Bitmap bitmap = getBitmapFromFile(file);
                    getActivity().runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            imageCollectorView.addImage(bitmap);
                        }
                    });
                }
            }
        }
    }
}.start();
RxJava:

Observable.from(folders)
    .flatMap(new Func1<File, Observable<File>>() {
        @Override
        public Observable<File> call(File file) {
            return Observable.from(file.listFiles());
        }
    })
    .filter(new Func1<File, Boolean>() {
        @Override
        public Boolean call(File file) {
            return file.getName().endsWith(".png");
        }
    })
    .map(new Func1<File, Bitmap>() {
        @Override
        public Bitmap call(File file) {
            return getBitmapFromFile(file);
        }
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Bitmap>() {
        @Override
        public void call(Bitmap bitmap) {
            imageCollectorView.addImage(bitmap);
        }
    });

不難發(fā)現(xiàn):RxJava好就好在什么復(fù)雜邏輯都能穿成一條線的簡潔。

6. RxJava的原理

  • RxJava的原理就是創(chuàng)建一個(gè)Observable對象來干活铆隘,然后使用各種操作符建立起來的鏈?zhǔn)讲僮髯慷妫腿缤魉€一樣,把你想要處理的數(shù)據(jù)一步一步地加工成你想要的成品膀钠,然后發(fā)射給Subscriber處理掏湾。
  • 看代碼:
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("Hello");
        subscriber.onNext("Hi");
        subscriber.onNext("Aloha");
        subscriber.onCompleted();
    }
});

這里傳入了一個(gè)OnSubscribe對象作為參數(shù)。OnSubscribe存儲在返回的Observable對象中肿嘲,它的作用相當(dāng)于一個(gè)計(jì)劃表融击,當(dāng)Observable被訂閱的時(shí)候,OnSubscribe對象中的call方法就會被自動(dòng)調(diào)用雳窟,事件序列就會依照設(shè)定依次觸發(fā)尊浪,這樣票摇,由被觀察者調(diào)用了觀察者的回調(diào)方法螟蒸,就實(shí)現(xiàn)了由被觀察者向觀察者的事件傳遞,即觀察者模式测柠。

7. 觀察者模式(簡單說)

7.1 觀察者模式需要解決的問題

  • A對象(觀察者)對B對象(被觀察者)的變化高度敏感誉结,需要在B對象變化的一瞬間做出反應(yīng)鹅士。

7.2 現(xiàn)實(shí)生活中的觀察與程序觀察者模式的區(qū)別

  • 生活中警察(觀察者)抓小偷(被觀察者),警察需要時(shí)時(shí)刻刻盯著小偷作案惩坑,當(dāng)小偷偷東西的那一刻掉盅,上前抓住也拜。
  • 程序中的觀察者模式:觀察者不用時(shí)時(shí)刻刻盯著被觀察者,而是采用訂閱的方式趾痘,觀察者告訴被觀察者你發(fā)生變化通知我慢哈。

7.3 很常見的觀察者模式

  • Button(被觀察者)與OnClickListener(觀察者),通過 setOnClickListener() 方法達(dá)成訂閱關(guān)系扼脐。
  • 采取這樣被動(dòng)的觀察方式岸军,既省去了反復(fù)檢索狀態(tài)的資源消耗,也能夠得到最高的反饋速度瓦侮。
  • 通過setOnClickListener()方法艰赞,Button持有OnClickListener的引用,當(dāng)用戶點(diǎn)擊時(shí)肚吏,Button會調(diào)用OnClickListener中的onClick方法方妖。抽象出來就是Button -> 被觀察者、OnClickListener -> 觀察者罚攀、setOnClickListener() -> 訂閱党觅,onClick() -> 事件。

8. RxJava與觀察者模式

  • RxJava 有四個(gè)基本概念:Observable (可觀察者斋泄,即被觀察者)杯瞻、 Observer (觀察者)、 subscribe (訂閱)炫掐、事件(被觀察者的行為)魁莉。Observable 和 Observer 通過 subscribe() 方法實(shí)現(xiàn)訂閱關(guān)系,從而 Observable 可以在需要的時(shí)候發(fā)出事件來通知 Observer募胃。
  • RxJava是通過擴(kuò)展的觀察者模式來實(shí)現(xiàn)的:與傳統(tǒng)觀察者模式不同旗唁, RxJava 的事件回調(diào)方法除了普通事件 onNext() (相當(dāng)于 onClick() / onEvent())之外,還定義了兩個(gè)特殊的事件:onCompleted() 和 onError()痹束。

9. RxJava基本實(shí)現(xiàn)

  • 添加依賴
    compile 'io.reactivex:rxjava:1.3.2'
    compile 'io.reactivex:rxandroid:1.2.1'
  • 創(chuàng)建Observer(觀察者):它決定事件觸發(fā)的時(shí)候?qū)⒂性鯓拥男袨?/li>
    /**
     * 創(chuàng)建觀察者:
     * Observer是一個(gè)接口检疫,Subscriber是在Observer的基礎(chǔ)上進(jìn)行了擴(kuò)展。
     */
    Subscriber mSubscriber = new Subscriber<String>() {

        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted");
        }

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

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

        @Override
        public void onStart() {
            Log.d(TAG, "onStart");
        }
    };

    Observer<String> mObserver = new Observer<String>() {
        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted");
        }

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

        @Override
        public void onNext(String s) {
            Log.d(TAG, "onNext:" + s);
        }
    };
  • 創(chuàng)建Obsevable(被觀察者):它決定什么時(shí)候觸發(fā)事件以及觸發(fā)怎樣的事件
    /**
     * 創(chuàng)建被觀察者
     */
    Observable observable = Observable.create(new Observable.OnSubscribe<String>() {

        @Override
        public void call(Subscriber<? super String> subscriber) {
            subscriber.onNext("Mr.Li");
            subscriber.onNext("Mr.Fu");
            subscriber.onNext("Mr.Zhao");
            subscriber.onCompleted();
        }
    });
  • 被觀察者訂閱觀察者
observable.subscribe(mSubscriber);
  • 鏈?zhǔn)秸{(diào)用
Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("Mr.Li");
        subscriber.onNext("Mr.Fu");
        subscriber.onNext("Mr.Zhao");
    }
}).subscribe(new Subscriber<String>() {
    @Override
    public void onCompleted() {
        Log.d(TAG, "onCompleted");
    }

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

    @Override
    public void onNext(String s) {
        Log.d(TAG, "onNext:" + s);
    }
});
  • Log
10-14 20:16:47.065 25587-25587/com.best.rxjava D/MainActivity: onStart
10-14 20:16:47.065 25587-25587/com.best.rxjava D/MainActivity: onNext:Mr.Li
10-14 20:16:47.065 25587-25587/com.best.rxjava D/MainActivity: onNext:Mr.Fu
10-14 20:16:47.065 25587-25587/com.best.rxjava D/MainActivity: onNext:Mr.Zhao
10-14 20:16:47.065 25587-25587/com.best.rxjava D/MainActivity: onCompleted

說明:先調(diào)用onStart方法祷嘶,接著調(diào)用兩個(gè)onNext方法屎媳,最后調(diào)用onCompleted方法。

10. Observer和Subscriber的關(guān)系

10.1 相同點(diǎn)

  • 基本使用方式是完全一樣:
Observer<String> observer = new Observer<String>() {
    @Override
    public void onNext(String s) {
        Log.d(tag, "Item: " + s);
    }

    @Override
    public void onCompleted() {
        Log.d(tag, "Completed!");
    }

    @Override
    public void onError(Throwable e) {
        Log.d(tag, "Error!");
    }
};
Subscriber<String> subscriber = new Subscriber<String>() {
    @Override
    public void onNext(String s) {
        Log.d(tag, "Item: " + s);
    }

    @Override
    public void onCompleted() {
        Log.d(tag, "Completed!");
    }

    @Override
    public void onError(Throwable e) {
        Log.d(tag, "Error!");
    }
};

說明:Subscriber是Observer的抽象類论巍,Subscriber 對 Observer 接口進(jìn)行了一些擴(kuò)展剿牺,但實(shí)質(zhì)上,在RxJava的subscribe過程中环壤,Observer也總是會先被轉(zhuǎn)換成一個(gè)Subscribe再使用晒来。

10.2 不同點(diǎn)

  • onStart(): 這是 Subscriber 增加的方法。它會在 subscribe 剛開始郑现,而事件還未發(fā)送之前被調(diào)用湃崩,可以用于做一些準(zhǔn)備工作荧降,例如數(shù)據(jù)的清零或重置。這是一個(gè)可選方法攒读,默認(rèn)情況下它的實(shí)現(xiàn)為空朵诫。需要注意的是,如果對準(zhǔn)備工作的線程有要求(例如彈出一個(gè)顯示進(jìn)度的對話框薄扁,這必須在主線程執(zhí)行)剪返, onStart() 就不適用了,因?yàn)樗偸窃?subscribe 所發(fā)生的線程被調(diào)用邓梅,而不能指定線程脱盲。要在指定的線程來做準(zhǔn)備工作,可以使用 doOnSubscribe() 方法日缨。

  • unsubscribe(): 這是 Subscriber 所實(shí)現(xiàn)的另一個(gè)接口 Subscription 的方法钱反,用于取消訂閱。在這個(gè)方法被調(diào)用后匣距,Subscriber 將不再接收事件面哥。一般在這個(gè)方法調(diào)用前,可以使用 isUnsubscribed() 先判斷一下狀態(tài)毅待。 unsubscribe() 這個(gè)方法很重要尚卫,因?yàn)樵?subscribe() 之后, Observable 會持有 Subscriber 的引用尸红,這個(gè)引用如果不能及時(shí)被釋放吱涉,將有內(nèi)存泄露的風(fēng)險(xiǎn)。所以最好保持一個(gè)原則:要在不再使用的時(shí)候盡快在合適的地方(例如 onPause() onStop() 等方法中)調(diào)用 unsubscribe() 來解除引用關(guān)系驶乾,以避免內(nèi)存泄露的發(fā)生。

11. 操作符分類

Rx操作符的類型分為創(chuàng)建操作符循签、變換操作符级乐、過濾操作符、組合操作符县匠、錯(cuò)誤處理操作符风科、輔助操作符、條件和布爾操作符乞旦、算術(shù)和聚合操作符及連接操作符等贼穆,而這些操作符類型下又有很多操作符,每個(gè)操作符可能還有很多變體兰粉。

12. 創(chuàng)建操作符

創(chuàng)建操作符,顧名思義故痊,它的作用就是創(chuàng)建Observable.這里講解create、just和from以及interval玖姑、range愕秫、repeat慨菱、deffer操作符。

  • create:用來創(chuàng)建被觀察者
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("Mr.Li");
        subscriber.onNext("Mr.Fu");
        subscriber.onNext("Mr.Zhao");
    }
})
  • just:對create的簡潔操作:將傳入的參數(shù)依次發(fā)送出來
Observable observable = Observable.just("Mr.Li", "Mr.Fu", "Mr.Zhao");
  • from(T[]) / from(Iterable<? extends T>):對create的簡潔操作:將傳入的數(shù)組或Iterable(集合或者列表) 拆分成具體對象后戴甩,依次發(fā)送出來符喝。
String[] s = {"Mr.Li", "Mr.Fu", "Mr.Zhao"};
Observable observable = Observable.from(s);
ArrayList<String> list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
list.add("4");
list.add("5");
list.add("6");
Observable observable = Observable.from(list);
  • interval:創(chuàng)建一個(gè)按固定時(shí)間間隔發(fā)射整數(shù)序列的Observable,相當(dāng)于定時(shí)器
    Observable.interval(3, TimeUnit.SECONDS)
    .subscribe(new Subscriber<Long>() {
        @Override
        public void onCompleted() {
            Log.d(TAG, "onCompleted");
        }
    
        @Override
        public void onError(Throwable e) {
            Log.d(TAG, "onError");
        }
    
        @Override
        public void onNext(Long aLong) {
            Log.d(TAG, "onNext:" + aLong);
        }
    });
    
10-14 14:51:42.089 3785-3802/com.best.rxjava D/MainActivity: onNext:0
10-14 14:51:45.089 3785-3802/com.best.rxjava D/MainActivity: onNext:1
10-14 14:51:48.089 3785-3802/com.best.rxjava D/MainActivity: onNext:2
10-14 14:51:51.089 3785-3802/com.best.rxjava D/MainActivity: onNext:3
10-14 14:51:54.089 3785-3802/com.best.rxjava D/MainActivity: onNext:4
10-14 14:51:57.088 3785-3802/com.best.rxjava D/MainActivity: onNext:5
10-14 14:52:00.089 3785-3802/com.best.rxjava D/MainActivity: onNext:6
10-14 14:52:03.089 3785-3802/com.best.rxjava D/MainActivity: onNext:7
10-14 14:52:06.088 3785-3802/com.best.rxjava D/MainActivity: onNext:8
10-14 14:52:09.089 3785-3802/com.best.rxjava D/MainActivity: onNext:9
10-14 14:52:12.089 3785-3802/com.best.rxjava D/MainActivity: onNext:10
..............
  • range:創(chuàng)建發(fā)射指定范圍的整數(shù)序列的Observable甜孤,可以拿來替代for循環(huán)协饲,發(fā)射一個(gè)范圍內(nèi)的有序整數(shù)序列。第一個(gè)參數(shù)是起始值缴川,并且不小于0茉稠;第二個(gè)參數(shù)為個(gè)數(shù)。
    Observable.range(1,5).subscribe(new Subscriber<Integer>() {
        @Override
        public void onCompleted() {
            Log.d(TAG_RANGE, "onCompleted");
        }

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

        @Override
        public void onNext(Integer integer) {
            Log.d(TAG_RANGE, "onNext:" + integer);
        }
    });
}

10-16 07:21:20.017 9564-9564/com.best.rxjava D/Range: onNext:1
10-16 07:21:20.017 9564-9564/com.best.rxjava D/Range: onNext:2
10-16 07:21:20.017 9564-9564/com.best.rxjava D/Range: onNext:3
10-16 07:21:20.017 9564-9564/com.best.rxjava D/Range: onNext:4
10-16 07:21:20.018 9564-9564/com.best.rxjava D/Range: onNext:5
10-16 07:21:20.018 9564-9564/com.best.rxjava D/Range: onCompleted
  • repeat:創(chuàng)建一個(gè)N次重復(fù)發(fā)射特定數(shù)據(jù)的Observable:
        Observable.range(0,3).repeat(3).subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.d(TAG_REPEAT, "onCompleted");
            }

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

            @Override
            public void onNext(Integer integer) {
                Log.d(TAG_REPEAT, "onNext:" + integer.intValue());
            }
        });
        
10-16 08:48:20.006 22148-22148/com.best.rxjava D/Repeat: onNext:0
10-16 08:48:20.006 22148-22148/com.best.rxjava D/Repeat: onNext:1
10-16 08:48:20.006 22148-22148/com.best.rxjava D/Repeat: onNext:2
10-16 08:48:20.007 22148-22148/com.best.rxjava D/Repeat: onNext:0
10-16 08:48:20.007 22148-22148/com.best.rxjava D/Repeat: onNext:1
10-16 08:48:20.007 22148-22148/com.best.rxjava D/Repeat: onNext:2
10-16 08:48:20.007 22148-22148/com.best.rxjava D/Repeat: onNext:0
10-16 08:48:20.007 22148-22148/com.best.rxjava D/Repeat: onNext:1
10-16 08:48:20.007 22148-22148/com.best.rxjava D/Repeat: onNext:2
10-16 08:48:20.008 22148-22148/com.best.rxjava D/Repeat: onCompleted
  • defer:延遲創(chuàng)建Observable,直到被觀察者訂閱才開始創(chuàng)建:
    Observable observable = Observable.defer(new Func0<Observable<String>>() {
        @Override
        public Observable<String> call() {
            return Observable.just(mString);
        }
    });
    observable.subscribe(new Subscriber<String>() {
        @Override
        public void onCompleted() {
            Log.d(TAG_DEFER, "onCompleted");
        }
    
        @Override
        public void onError(Throwable e) {
            Log.d(TAG_DEFER, "onError");
        }
    
        @Override
        public void onNext(String s) {
            Log.d(TAG_DEFER, "onNext:" + s);
        }
    });
    
    
10-16 08:48:19.993 22148-22148/com.best.rxjava D/Deffer: onNext:null
10-16 08:48:19.993 22148-22148/com.best.rxjava D/Deffer: onCompleted
        Observable observable = Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                return Observable.just(mString);
            }
        });
        mString = "RxJava";
        observable.subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG_DEFER, "onCompleted");
            }

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

            @Override
            public void onNext(String s) {
                Log.d(TAG_DEFER, "onNext:" + s);
            }
        });
10-16 22:01:18.496 30581-30581/? D/Deffer: onNext:RxJava
10-16 22:01:18.496 30581-30581/? D/Deffer: onCompleted

13. 變換操作符

變換操作符二跋,顧名思義战惊,它的作用就是對Observable發(fā)射的數(shù)據(jù)按照一定的規(guī)則做一些變換操作,然后將變換后的數(shù)據(jù)發(fā)射出去扎即。這里講解map吞获、flatmap、cast谚鄙、flatMapIterable各拷、buffer和groupBy.

  • map:通過指定一個(gè)Func對象,將Observable轉(zhuǎn)換為一個(gè)新的Observable對象并發(fā)射闷营,觀察者將收到新的Observable處理:意思就是將一個(gè)Observable轉(zhuǎn)為另外一個(gè)新的Observable烤黍。
//將Integer轉(zhuǎn)換為String
        Observable.just(123).map(new Func1<Integer, String>() {
            @Override
            public String call(Integer integer) {
                return integer+"";
            }
        }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG_MAP, "onCompleted");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG_MAP, "onNext:" + s);
            }
        });
  • flatmap、cast:將Observable發(fā)射的數(shù)據(jù)集合變換為Observable集合傻盟,然后將這些Observable發(fā)射的數(shù)據(jù)平坦化地放進(jìn)一個(gè)單獨(dú)的Observable速蕊。cast操作符的作用是強(qiáng)制將Observable發(fā)射的所有數(shù)據(jù)轉(zhuǎn)換為指定類型。
/**
*需求:訪問網(wǎng)絡(luò)娘赴,但是要訪問同一個(gè)Host的多個(gè)界面规哲,我們可以使用fo*r循環(huán)在每個(gè)界面的URL前添加Host,但是RxJava提供了一個(gè)更方便的操*/作诽表。
final String Host = "http://blog.csdn.net/";
        List<String> mlist = new ArrayList<>();
        mlist.add("fukaiqiang01");
        mlist.add("fukaiqiang02");
        mlist.add("fukaiqiang03");
        mlist.add("fukaiqiang04");
        mlist.add("fukaiqiang05");
        Observable.from(mlist).flatMap(new Func1<String, Observable<?>>() {
            @Override
            public Observable<?> call(String s) {
                return Observable.just(Host + s);
            }
        }).cast(String.class).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG_FLATMAP, "onCompleted");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG_FLATMAP, "onNext:" + s);
            }
        });
        
10-17 09:23:28.255 14668-14668/? D/FlatMap: onNext:http://blog.csdn.net/fukaiqiang01
10-17 09:23:28.255 14668-14668/? D/FlatMap: onNext:http://blog.csdn.net/fukaiqiang02
10-17 09:23:28.255 14668-14668/? D/FlatMap: onNext:http://blog.csdn.net/fukaiqiang03
10-17 09:23:28.255 14668-14668/? D/FlatMap: onNext:http://blog.csdn.net/fukaiqiang04
10-17 09:23:28.255 14668-14668/? D/FlatMap: onNext:http://blog.csdn.net/fukaiqiang05
10-17 09:23:28.255 14668-14668/? D/FlatMap: onCompleted

說明:首先用ArrayList存儲要訪問的界面URL,然后通過flatMap轉(zhuǎn)換成Observable唉锌。cast操作符將Observable中的數(shù)據(jù)轉(zhuǎn)換為String類型。

注意:flatMap的合并允許交叉竿奏,也就是說可能會交錯(cuò)地發(fā)送事件袄简,最終結(jié)果的順序可能并不是原始Observable發(fā)送時(shí)的順序。

  • flatMapIterable:將數(shù)據(jù)轉(zhuǎn)換為Iterable泛啸,在Iterable里面進(jìn)行數(shù)據(jù)的處理:
Observable.just(1,2,3).flatMapIterable(new Func1<Integer, Iterable<Integer>>() {
            @Override
            public Iterable<Integer> call(Integer integer) {
                List<Integer> mlist = new ArrayList<Integer>();
                mlist.add(integer+1);
                return mlist;
            }
        }).subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Integer integer) {
                Log.d(FLATMAPITERABLE, "onNext:" + integer);
            }
        });
  • buffer:顧名思義绿语,設(shè)置緩沖區(qū)大小:它可以將原Observable變換為一個(gè)新的Observable,這個(gè)新的Observable每次發(fā)射一組列表值汞舱,而不是一個(gè)一個(gè)發(fā)射伍纫。buffer意思就是設(shè)置緩存容量值。
Observable.just(1,2,3,4,5,6).buffer(3).subscribe(new Subscriber<List<Integer>>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(List<Integer> integers) {
                for (Integer integer : integers){
                    Log.d(BUFFER,"buffer:"+integer);
                }
                Log.d(BUFFER,"---------------------");
            }
        });
        
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: buffer:1
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: buffer:2
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: buffer:3
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: ---------------------
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: buffer:4
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: buffer:5
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: buffer:6
10-17 11:38:47.340 30993-30993/com.best.rxjava D/Buffer: ---------------------
  • groupBy:用于分組元素昂芜,將源Observable變換成一個(gè)發(fā)射Observables的新Observable(分組后的)莹规。它們中的每一個(gè)新Observable都發(fā)射一組指定的數(shù)據(jù)。
        Student s1 = new Student("楊過", "SSS");
        Student s2 = new Student("金輪法王", "SSS");
        Student s3 = new Student("周伯通", "S");
        Student s4 = new Student("東邪", "S");
        Student s5 = new Student("吸毒", "S");
        Student s6 = new Student("南帝", "S");
        Student s7 = new Student("北丐", "S");
        Student s8 = new Student("中神通", "SS");
        Student s9 = new Student("王蓉", "A");
        Observable<GroupedObservable<String, Student>> GroupedObservable =
                Observable.just(s1, s2, s3, s4, s5, s6, s7, s8, s9).groupBy(new Func1<Student, String>() {
                    @Override
                    public String call(Student student) {
                        return student.getLevel();
                    }
                });
        Observable.concat(GroupedObservable).subscribe(new Subscriber<Student>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Student student) {
                Log.d(GROUPBY, "groupby:" + student.getName() + "-----" + student.getLevel());
            }
        });
        
10-17 13:07:42.583 11707-11707/? D/GroupBy: groupby:楊過-----SSS
10-17 13:07:42.583 11707-11707/? D/GroupBy: groupby:金輪法王-----SSS
10-17 13:07:42.583 11707-11707/? D/GroupBy: groupby:周伯通-----S
10-17 13:07:42.584 11707-11707/? D/GroupBy: groupby:東邪-----S
10-17 13:07:42.584 11707-11707/? D/GroupBy: groupby:吸毒-----S
10-17 13:07:42.584 11707-11707/? D/GroupBy: groupby:南帝-----S
10-17 13:07:42.584 11707-11707/? D/GroupBy: groupby:北丐-----S
10-17 13:07:42.584 11707-11707/? D/GroupBy: groupby:中神通-----SS
10-17 13:07:42.584 11707-11707/? D/GroupBy: groupby:王蓉-----A

說明:這里創(chuàng)建了9個(gè)學(xué)生泌神,按照其功夫水平的高低良漱,對其進(jìn)行了劃分,從高到低依次是SSS欢际、SS母市、S、A.使用groupby可以幫助我們隊(duì)某一個(gè)key值進(jìn)行分組损趋,將相同的key值數(shù)據(jù)排在一起患久。這里的key指的就是等級,其中concat是組合操作符浑槽,后面會介紹蒋失。

14. 推薦博客:

如果Recyclerview基礎(chǔ)不太好,歡迎跳轉(zhuǎn)閱讀 http://www.reibang.com/p/3eb81f50f4db

15. 后續(xù)

如果大家喜歡這篇文章桐玻,歡迎點(diǎn)贊篙挽;如果想看更多前端移動(dòng)端后端Java或Python方面的技術(shù),歡迎關(guān)注镊靴!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末铣卡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子偏竟,更是在濱河造成了極大的恐慌煮落,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踊谋,死亡現(xiàn)場離奇詭異蝉仇,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)褪子,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門量淌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骗村,“玉大人嫌褪,你說我怎么就攤上這事∨吖桑” “怎么了笼痛?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我缨伊,道長摘刑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任刻坊,我火速辦了婚禮枷恕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谭胚。我一直安慰自己徐块,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布灾而。 她就那樣靜靜地躺著胡控,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旁趟。 梳的紋絲不亂的頭發(fā)上昼激,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音锡搜,去河邊找鬼橙困。 笑死,一個(gè)胖子當(dāng)著我的面吹牛余爆,可吹牛的內(nèi)容都是我干的纷宇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼蛾方,長吁一口氣:“原來是場噩夢啊……” “哼像捶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起桩砰,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤拓春,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后亚隅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硼莽,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年煮纵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了懂鸵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡行疏,死狀恐怖匆光,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情酿联,我是刑警寧澤终息,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布夺巩,位于F島的核電站,受9級特大地震影響周崭,放射性物質(zhì)發(fā)生泄漏柳譬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一续镇、第九天 我趴在偏房一處隱蔽的房頂上張望美澳。 院中可真熱鬧,春花似錦摸航、人聲如沸人柿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凫岖。三九已至,卻和暖如春逢净,著一層夾襖步出監(jiān)牢的瞬間哥放,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工爹土, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留甥雕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓胀茵,卻偏偏與公主長得像社露,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子琼娘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位峭弟,與響應(yīng)式編程作為結(jié)合使用的,對什么是操作脱拼、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,841評論 0 10
  • 作者寄語 很久之前就想寫一個(gè)專題瞒瘸,專寫Android開發(fā)框架,專題的名字叫 XXX 從入門到放棄 熄浓,沉淀了這么久情臭,...
    戴定康閱讀 7,615評論 13 85
  • 我從去年開始使用 RxJava ,到現(xiàn)在一年多了赌蔑。今年加入了 Flipboard 后俯在,看到 Flipboard 的...
    Jason_andy閱讀 5,456評論 7 62
  • 轉(zhuǎn)一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong閱讀 905評論 0 2
  • 不知道什么時(shí)候開始 失去了很多感覺 不知道食物的味道 雨點(diǎn)的大小 甚至疼痛感 聞不出食物散發(fā)的沁人心脾的香味 雨點(diǎn)...
    溫暖dream閱讀 226評論 4 2