這可能是最好的RxJava 2.x 入門教程(四)

這可能是最好的 RxJava 2.x 入門教程系列專欄
文章鏈接:
這可能是最好的 RxJava 2.x 入門教程(完結(jié)版)【重磅推出】
這可能是最好的 RxJava 2.x 入門教程(一)
這可能是最好的 RxJava 2.x 入門教程(二)
這可能是最好的 RxJava 2.x 入門教程(三)
這可能是最好的 RxJava 2.x 入門教程(四)
這可能是最好的 RxJava 2.x 入門教程(五)
GitHub 代碼同步更新:https://github.com/nanchen2251/RxJava2Examples
為了滿足大家的饑渴難耐箩张,GitHub 將同步更新代碼试浙,主要包含基本的代碼封裝怕轿,RxJava 2.x 所有操作符應(yīng)用場(chǎng)景介紹和實(shí)際應(yīng)用場(chǎng)景,后期除了 RxJava 可能還會(huì)增添其他東西寸宏,總之嗜愈,GitHub 上的 Demo 專為大家傾心打造凌净。傳送門:https://github.com/nanchen2251/RxJava2Examples

前言

最近很多小伙伴私信我赏胚,說(shuō)自己很懊惱,對(duì)于 RxJava 2.x 系列一看就能明白矾缓,但自己寫卻又寫不出來(lái)怀酷。如果 LZ 能放上實(shí)戰(zhàn)情景教程就最好不過(guò)了。也是哈嗜闻,單講我們的操作符胰坟,也讓我們的教程不溫不火,但 LZ 自己選擇的路泞辐,那跪著也要走完呀。所以竞滓,也就讓我可憐的小伙伴們?nèi)倘塘烁篮穑僮鞣R上就講完了。

正題

Single

顧名思義商佑,Single 只會(huì)接收一個(gè)參數(shù)锯茄,而 SingleObserver 只會(huì)調(diào)用 onError() 或者 onSuccess()

Single.just(new Random().nextInt())
                .subscribe(new SingleObserver<Integer>() {
                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onSuccess(@NonNull Integer integer) {
                        mRxOperatorsText.append("single : onSuccess : "+integer+"\n");
                        Log.e(TAG, "single : onSuccess : "+integer+"\n" );
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        mRxOperatorsText.append("single : onError : "+e.getMessage()+"\n");
                        Log.e(TAG, "single : onError : "+e.getMessage()+"\n");
                    }
                });

輸出:


distinct

去重操作符茶没,簡(jiǎn)單的作用就是去重肌幽。


Observable.just(1, 1, 1, 2, 2, 3, 4, 5)
                .distinct()
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) throws Exception {
                        mRxOperatorsText.append("distinct : " + integer + "\n");
                        Log.e(TAG, "distinct : " + integer + "\n");
                    }
                });

輸出:



很明顯,發(fā)射器發(fā)送的事件抓半,在接收的時(shí)候被去重了喂急。

debounce

去除發(fā)送頻率過(guò)快的項(xiàng),看起來(lái)好像沒(méi)啥用處笛求,但你信我廊移,后面絕對(duì)有地方很有用武之地糕簿。


Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Integer> emitter) throws Exception {
                // send events with simulated time wait
                emitter.onNext(1); // skip
                Thread.sleep(400);
                emitter.onNext(2); // deliver
                Thread.sleep(505);
                emitter.onNext(3); // skip
                Thread.sleep(100);
                emitter.onNext(4); // deliver
                Thread.sleep(605);
                emitter.onNext(5); // deliver
                Thread.sleep(510);
                emitter.onComplete();
            }
        }).debounce(500, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) throws Exception {
                        mRxOperatorsText.append("debounce :" + integer + "\n");
                        Log.e(TAG,"debounce :" + integer + "\n");
                    }
                });

輸出:



代碼很清晰,去除發(fā)送間隔時(shí)間小于 500 毫秒的發(fā)射事件狡孔,所以 1 和 3 被去掉了懂诗。

defer

簡(jiǎn)單地時(shí)候就是每次訂閱都會(huì)創(chuàng)建一個(gè)新的 Observable,并且如果沒(méi)有被訂閱苗膝,就不會(huì)產(chǎn)生新的 Observable殃恒。

Observable<Integer> observable = Observable.defer(new Callable<ObservableSource<Integer>>() {
            @Override
            public ObservableSource<Integer> call() throws Exception {
                return Observable.just(1, 2, 3);
            }
        });


        observable.subscribe(new Observer<Integer>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull Integer integer) {
                mRxOperatorsText.append("defer : " + integer + "\n");
                Log.e(TAG, "defer : " + integer + "\n");
            }

            @Override
            public void onError(@NonNull Throwable e) {
                mRxOperatorsText.append("defer : onError : " + e.getMessage() + "\n");
                Log.e(TAG, "defer : onError : " + e.getMessage() + "\n");
            }

            @Override
            public void onComplete() {
                mRxOperatorsText.append("defer : onComplete\n");
                Log.e(TAG, "defer : onComplete\n");
            }
        });

輸出:


last

last 操作符僅取出可觀察到的最后一個(gè)值,或者是滿足某些條件的最后一項(xiàng)辱揭。

Observable.just(1, 2, 3)
                .last(4)
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) throws Exception {
                        mRxOperatorsText.append("last : " + integer + "\n");
                        Log.e(TAG, "last : " + integer + "\n");
                    }
                });

輸出:


merge

merge 顧名思義离唐,熟悉版本控制工具的你一定不會(huì)不知道 merge 命令,而在 Rx 操作符中界阁,merge 的作用是把多個(gè) Observable 結(jié)合起來(lái)侯繁,接受可變參數(shù),也支持迭代器集合泡躯。注意它和 concat 的區(qū)別在于贮竟,不用等到 發(fā)射器 A 發(fā)送完所有的事件再進(jìn)行發(fā)射器 B 的發(fā)送。

Observable.merge(Observable.just(1, 2), Observable.just(3, 4, 5))
                .subscribe(new Consumer<Integer>() {
                    @Override
                    public void accept(@NonNull Integer integer) throws Exception {
                        mRxOperatorsText.append("merge :" + integer + "\n");
                        Log.e(TAG, "accept: merge :" + integer + "\n" );
                    }
                });

輸出:


reduce

reduce 操作符每次用一個(gè)方法處理一個(gè)值较剃,可以有一個(gè) seed 作為初始值咕别。

Observable.just(1, 2, 3)
               .reduce(new BiFunction<Integer, Integer, Integer>() {
                   @Override
                   public Integer apply(@NonNull Integer integer, @NonNull Integer integer2) throws Exception {
                       return integer + integer2;
                   }
               }).subscribe(new Consumer<Integer>() {
           @Override
           public void accept(@NonNull Integer integer) throws Exception {
               mRxOperatorsText.append("reduce : " + integer + "\n");
               Log.e(TAG, "accept: reduce : " + integer + "\n");
           }
       });

輸出:



可以看到,代碼中写穴,我們中間采用 reduce 惰拱,支持一個(gè) function 為兩數(shù)值相加,所以應(yīng)該最后的值是:1 + 2 = 3 + 3 = 6 啊送, 而Log 日志完美解決了我們的問(wèn)題偿短。

scan

scan 操作符作用和上面的 reduce 一致,唯一區(qū)別是 reduce 是個(gè)只追求結(jié)果的壞人馋没,而 scan 會(huì)始終如一地把每一個(gè)步驟都輸出昔逗。

Observable.just(1, 2, 3)
                .scan(new BiFunction<Integer, Integer, Integer>() {
                    @Override
                    public Integer apply(@NonNull Integer integer, @NonNull Integer integer2) throws Exception {
                        return integer + integer2;
                    }
                }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(@NonNull Integer integer) throws Exception {
                mRxOperatorsText.append("scan " + integer + "\n");
                Log.e(TAG, "accept: scan " + integer + "\n");
            }
        });

輸出:



看日志,沒(méi)毛病篷朵。

window

按照實(shí)際劃分窗口勾怒,將數(shù)據(jù)發(fā)送給不同的 Observable

mRxOperatorsText.append("window\n");
       Log.e(TAG, "window\n");
       Observable.interval(1, TimeUnit.SECONDS) // 間隔一秒發(fā)一次
               .take(15) // 最多接收15個(gè)
               .window(3, TimeUnit.SECONDS)
               .subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread())
               .subscribe(new Consumer<Observable<Long>>() {
                   @Override
                   public void accept(@NonNull Observable<Long> longObservable) throws Exception {
                       mRxOperatorsText.append("Sub Divide begin...\n");
                       Log.e(TAG, "Sub Divide begin...\n");
                       longObservable.subscribeOn(Schedulers.io())
                               .observeOn(AndroidSchedulers.mainThread())
                               .subscribe(new Consumer<Long>() {
                                   @Override
                                   public void accept(@NonNull Long aLong) throws Exception {
                                       mRxOperatorsText.append("Next:" + aLong + "\n");
                                       Log.e(TAG, "Next:" + aLong + "\n");
                                   }
                               });
                   }
               });

輸出:


寫在最后

至此,大部分 RxJava 2.x 的操作符就告一段落了声旺,當(dāng)然還有一些沒(méi)有提到的操作符笔链,不是說(shuō)它們不重要,而是 LZ 也要考慮大家的情況腮猖,接下來(lái)就會(huì)根據(jù)實(shí)際應(yīng)用場(chǎng)景來(lái)對(duì) RxJava 2.x 發(fā)起沖鋒鉴扫。如果想看更多的數(shù)據(jù),請(qǐng)移步 GitHub:https://github.com/nanchen2251/RxJava2Examples

做不完的開(kāi)源澈缺,寫不完的矯情幔妨。歡迎掃描下方二維碼或者公眾號(hào)搜索「nanchen」關(guān)注我的微信公眾號(hào)鹦赎,目前多運(yùn)營(yíng) Android ,盡自己所能為你提升误堡。如果你喜歡古话,為我點(diǎn)贊分享吧~


nanchen
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市锁施,隨后出現(xiàn)的幾起案子陪踩,更是在濱河造成了極大的恐慌,老刑警劉巖悉抵,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肩狂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡姥饰,警方通過(guò)查閱死者的電腦和手機(jī)傻谁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)列粪,“玉大人审磁,你說(shuō)我怎么就攤上這事∑褡” “怎么了态蒂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)费什。 經(jīng)常有香客問(wèn)我钾恢,道長(zhǎng),這世上最難降的妖魔是什么鸳址? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任瘩蚪,我火速辦了婚禮,結(jié)果婚禮上稿黍,老公的妹妹穿的比我還像新娘募舟。我一直安慰自己,他們只是感情好闻察,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著琢锋,像睡著了一般辕漂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吴超,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天钉嘹,我揣著相機(jī)與錄音,去河邊找鬼鲸阻。 笑死跋涣,一個(gè)胖子當(dāng)著我的面吹牛缨睡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陈辱,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼奖年,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了沛贪?” 一聲冷哼從身側(cè)響起陋守,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎利赋,沒(méi)想到半個(gè)月后水评,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡媚送,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年中燥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塘偎。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疗涉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出式塌,到底是詐尸還是另有隱情博敬,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布峰尝,位于F島的核電站偏窝,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏武学。R本人自食惡果不足惜祭往,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望火窒。 院中可真熱鬧硼补,春花似錦、人聲如沸熏矿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)票编。三九已至褪储,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慧域,已是汗流浹背鲤竹。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昔榴,地道東北人辛藻。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓碘橘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吱肌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痘拆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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