這可能是最好的RxJava 2.x 入門(mén)教程(三)

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

前言

年輕的老司機(jī)們,我這么勤的為大家分享,卻少有催更的,好吧。其實(shí)寫(xiě)這個(gè)系列不是為了吸睛,那咱們繼續(xù)寫(xiě)我們的 RxJava 2.x 的操作符。

正題

distinct

這個(gè)操作符非常的簡(jiǎn)單、通俗、易懂,就是簡(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");
                    }
                });

輸出:


Log 日志顯而易見(jiàn),我們?cè)诮?jīng)過(guò) dinstinct() 后接收器接收到的事件只有1,2,3,4,5了。

Filter

信我,Filter 你會(huì)很常用的,它的作用也很簡(jiǎn)單,過(guò)濾器嘛。可以接受一個(gè)參數(shù),讓其過(guò)濾掉不符合我們條件的值

Observable.just(1, 20, 65, -5, 7, 19)
                .filter(new Predicate<Integer>() {
                    @Override
                    public boolean test(@NonNull Integer integer) throws Exception {
                        return integer >= 10;
                    }
                }).subscribe(new Consumer<Integer>() {
            @Override
            public void accept(@NonNull Integer integer) throws Exception {
                mRxOperatorsText.append("filter : " + integer + "\n");
                Log.e(TAG, "filter : " + integer + "\n");
            }
        });

輸出:



可以看到,我們過(guò)濾器舍去了小于 10 的值,所以最好的輸出只有 20, 65, 19。

buffer

buffer 操作符接受兩個(gè)參數(shù),buffer(count,skip),作用是將 Observable 中的數(shù)據(jù)按 skip (步長(zhǎng)) 分成最大不超過(guò) count 的 buffer ,然后生成一個(gè) Observable 。也許你還不太理解,我們可以通過(guò)我們的示例圖和示例代碼來(lái)進(jìn)一步深化它。

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

輸出:


如圖,我們把 1, 2, 3, 4, 5 依次發(fā)射出來(lái),經(jīng)過(guò) buffer 操作符,其中參數(shù) skip 為 2, count 為 3,而我們的輸出 依次是 123,345,5。顯而易見(jiàn),我們 buffer 的第一個(gè)參數(shù)是 count,代表最大取值,在事件足夠的時(shí)候,一般都是取 count 個(gè)值,然后每次跳過(guò) skip 個(gè)事件。其實(shí)看 Log 日志,我相信大家都明白了。

timer

timer 很有意思,相當(dāng)于一個(gè)定時(shí)任務(wù)。在 1.x 中它還可以執(zhí)行間隔邏輯,但在 2.x 中此功能被交給了 interval,下一個(gè)會(huì)介紹。但需要注意的是,timerinterval 均默認(rèn)在新線(xiàn)程。

mRxOperatorsText.append("timer start : " + TimeUtil.getNowStrTime() + "\n");
        Log.e(TAG, "timer start : " + TimeUtil.getNowStrTime() + "\n");
        Observable.timer(2, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()) // timer 默認(rèn)在新線(xiàn)程,所以需要切換回主線(xiàn)程
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(@NonNull Long aLong) throws Exception {
                        mRxOperatorsText.append("timer :" + aLong + " at " + TimeUtil.getNowStrTime() + "\n");
                        Log.e(TAG, "timer :" + aLong + " at " + TimeUtil.getNowStrTime() + "\n");
                    }
                });

輸出:



顯而易見(jiàn),當(dāng)我們兩次點(diǎn)擊按鈕觸發(fā)這個(gè)事件的時(shí)候,接收被延遲了 2 秒。

interval

如同我們上面可說(shuō),interval 操作符用于間隔時(shí)間執(zhí)行某個(gè)操作,其接受三個(gè)參數(shù),分別是第一次發(fā)送延遲,間隔時(shí)間,時(shí)間單位。

mRxOperatorsText.append("interval start : " + TimeUtil.getNowStrTime() + "\n");
       Log.e(TAG, "interval start : " + TimeUtil.getNowStrTime() + "\n");
       Observable.interval(3,2, TimeUnit.SECONDS)
               .subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread()) // 由于interval默認(rèn)在新線(xiàn)程,所以我們應(yīng)該切回主線(xiàn)程
               .subscribe(new Consumer<Long>() {
                   @Override
                   public void accept(@NonNull Long aLong) throws Exception {
                       mRxOperatorsText.append("interval :" + aLong + " at " + TimeUtil.getNowStrTime() + "\n");
                       Log.e(TAG, "interval :" + aLong + " at " + TimeUtil.getNowStrTime() + "\n");
                   }
               });

輸出:



如同 Log 日志一樣,第一次延遲了 3 秒后接收到,后面每次間隔了 2 秒。
然而,心細(xì)的小伙伴可能會(huì)發(fā)現(xiàn),由于我們這個(gè)是間隔執(zhí)行,所以當(dāng)我們的Activity 都銷(xiāo)毀的時(shí)候,實(shí)際上這個(gè)操作還依然在進(jìn)行,所以,我們得花點(diǎn)小心思讓我們?cè)诓恍枰臅r(shí)候干掉它。查看源碼發(fā)現(xiàn),我們subscribe(Cousumer<? super T> onNext)返回的是Disposable,我們可以在這上面做文章。


@Override
   protected void doSomething() {
       mRxOperatorsText.append("interval start : " + TimeUtil.getNowStrTime() + "\n");
       Log.e(TAG, "interval start : " + TimeUtil.getNowStrTime() + "\n");
       mDisposable = Observable.interval(3, 2, TimeUnit.SECONDS)
               .subscribeOn(Schedulers.io())
               .observeOn(AndroidSchedulers.mainThread()) // 由于interval默認(rèn)在新線(xiàn)程,所以我們應(yīng)該切回主線(xiàn)程
               .subscribe(new Consumer<Long>() {
                   @Override
                   public void accept(@NonNull Long aLong) throws Exception {
                       mRxOperatorsText.append("interval :" + aLong + " at " + TimeUtil.getNowStrTime() + "\n");
                       Log.e(TAG, "interval :" + aLong + " at " + TimeUtil.getNowStrTime() + "\n");
                   }
               });
   }

   @Override
   protected void onDestroy() {
       super.onDestroy();
       if (mDisposable != null && !mDisposable.isDisposed()) {
           mDisposable.dispose();
       }
   }

哈哈,再次驗(yàn)證,解決了我們的疑惑。

doOnNext

其實(shí)覺(jué)得 doOnNext 應(yīng)該不算一個(gè)操作符,但考慮到其常用性,我們還是咬咬牙將它放在了這里。它的作用是讓訂閱者在接收到數(shù)據(jù)之前干點(diǎn)有意思的事情。假如我們?cè)讷@取到數(shù)據(jù)之前想先保存一下它,無(wú)疑我們可以這樣實(shí)現(xiàn)。

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

輸出:


skip

skip 很有意思,其實(shí)作用就和字面意思一樣,接受一個(gè) long 型參數(shù) count ,代表跳過(guò) count 個(gè)數(shù)目開(kāi)始接收。

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

輸出:


take

take,接受一個(gè) long 型參數(shù) count ,代表至多接收 count 個(gè)數(shù)據(jù)。

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

輸出:


just

just,沒(méi)什么好說(shuō)的,其實(shí)在前面各種例子都說(shuō)明了,就是一個(gè)簡(jiǎn)單的發(fā)射器依次調(diào)用 onNext() 方法。

Observable.just("1", "2", "3")
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(@NonNull String s) throws Exception {
                        mRxOperatorsText.append("accept : onNext : " + s + "\n");
                        Log.e(TAG,"accept : onNext : " + s + "\n" );
                    }
                });

輸出:


寫(xiě)在最后

好吧,本節(jié)先講到這里,下節(jié)我們還是繼續(xù)講簡(jiǎn)單的操作符,雖然我們的教程比較枯燥,現(xiàn)在也不那么受人關(guān)注,但后面的系列我相信大家一定會(huì)非常喜歡的,我們下期再見(jiàn)!
代碼全部同步到GitHub:https://github.com/nanchen2251/RxJava2Examples

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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