RxJava 學(xué)習(xí)進行中-Scan&Debounce&ThrottleWithTimeout

RX

1.Scan

連續(xù)地對數(shù)據(jù)序列的每一項應(yīng)用一個函數(shù),然后連續(xù)發(fā)射結(jié)果
操作符對原始Observable發(fā)射的第一項數(shù)據(jù)應(yīng)用一個函數(shù)吨凑,然后將那個函數(shù)的結(jié)果作為自己的第一項數(shù)據(jù)發(fā)射捍歪。它將函數(shù)的結(jié)果同第二項數(shù)據(jù)一起填充給這個函數(shù)來產(chǎn)生它自己的第二項數(shù)據(jù)。它持續(xù)進行這個過程來產(chǎn)生剩余的數(shù)據(jù)序列鸵钝。這個操作符在某些情況下被叫做accumulator

看完文檔糙臼,感覺Scan叫的太牽強,不過自己也想不出別這個更好的詞來恩商,當(dāng)然accumulator更加得形象变逃。它接受的參數(shù)可以只是一個固定有兩個參數(shù)一個輸出的Func2<>

        Character[] strs = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','i'};
        Observable<Character> origin = Observable.from(strs);

        origin.scan("",new Func2<String, Character, String>() {

            @Override
            public String call(String s, Character character) {
                String result = s+character.charValue();
                Log.d("scan","拼接字符 "+s +" + "+character.charValue() +" = " +result);
                return result;
            }
        }).subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String result) {
                Log.d("scan","接收到的 result = "+result);
            }
        });

可以看到Scan還有一個參數(shù)怠堪,這里是一個空字符串揽乱,這是另一種形式,第一個參數(shù)是你預(yù)先設(shè)定好的初值粟矿,第二個參數(shù)則是你的函數(shù)凰棉,初值會作為第一個值加入到方法中去。

注意

A = C , B隨意
    scan("",new Func2<A, B, C>() {
            @Override
            public C call(A a,  B b) {
                return .....;
            }
        })

這是因為Scan會接受上一個scan返回值作為第一個參數(shù)陌粹,當(dāng)然如果你寫不一樣了撒犀,AS會提醒你的,一片紅色波浪線...

運行結(jié)果

2.Debounce & ThrottleWithTimeout

先貼上官方說明

僅在過了一段指定的時間還沒發(fā)射數(shù)據(jù)時才發(fā)射一個數(shù)據(jù),會過濾掉發(fā)射速率過快的數(shù)據(jù)項。

一開我的理解是這樣的或舞,在一定時間段內(nèi)發(fā)送在這個時間段內(nèi)輸出的最后一個數(shù)據(jù)

如下圖

錯誤的理解

于是乎荆姆,我寫了以下代碼做測試

        Observable.interval(1, TimeUnit.SECONDS)//每隔1秒發(fā)送一個Long型的從0自增的數(shù)
                .debounce(3, TimeUnit.SECONDS)
                .subscribe(new Action1<Long>() {
                    @Override
                    public void call(Long aLong) {
                        Log.d("debounce","aLong num = "+aLong);
                    }
                });

然而,打印出來的是一片空白映凳。啥都沒有胆筒!我懵逼了,跟想象中不一樣拔嚎怼腐泻!

于是乎請教了搜索引擎,找到呼嘯而過11寫的代碼

   Observable.create(new Observable.OnSubscribe<Integer>() {
        @Override
        public void call(Subscriber<? super Integer> subscriber) {
            if(subscriber.isUnsubscribed()) return;
            try {
                //產(chǎn)生結(jié)果的間隔時間分別為100队询、200派桩、300...900毫秒
                for (int i = 1; i < 10; i++) {
                    subscriber.onNext(i);
                    Thread.sleep(i * 100);
                }
                subscriber.onCompleted();
            }catch(Exception e){
                subscriber.onError(e);
            }
        }
    }).subscribeOn(Schedulers.newThread())
            .debounce(400, TimeUnit.MILLISECONDS)  //超時時間為400毫秒
            .subscribe(
                    new Action1<Integer>() {
                        @Override
                        public void call(Integer integer) {
                            Log.d("debounce","onnext aLong num = "+integer);
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            Log.d("debounce","onerror ");
                        }
                    }, new Action0() {
                        @Override
                        public void call() {
                            Log.d("debounce","oncompleted ");
                        }
                    });

運行結(jié)果如下:
Next:4
Next:5
Next:6
Next:7
Next:8
Next:9
completed!

恍然大悟,其真正含義是在輸出了一個數(shù)據(jù)后的一段時間內(nèi)蚌斩,沒有再次輸出新的數(shù)據(jù)铆惑,則把這個數(shù)據(jù)真正的發(fā)送出去;假如在這段時間內(nèi)有新的數(shù)據(jù)輸出送膳,則以這個數(shù)據(jù)作為將要發(fā)送的數(shù)據(jù)項员魏,并且重置這個時間段,重新計時叠聋。

正確的理解

我把之前的測試代碼按照我的理解修改了一下

/**debounce設(shè)置時間間隔為3秒撕阎,interval每一秒發(fā)送一個數(shù)據(jù)項,中間用filter過濾掉了第1碌补、2虏束、3,6厦章、
7镇匀,11、12袜啃、13汗侵、14秒的數(shù)據(jù)項,就是為了看第0項群发,第5項晰韵,第10項能否發(fā)送,按理解熟妓,在3秒的時間間隔
內(nèi)沒有新數(shù)據(jù)項到達才會發(fā)送最后一個數(shù)據(jù)項雪猪,即0、10項是可以被發(fā)送的滑蚯,而5不可以;y以及使用map打印
出真正到達debounce的數(shù)據(jù)項,方便理解
*/
        Observable.interval(1, TimeUnit.SECONDS)//每隔1秒發(fā)送一個Long型的從0自增的數(shù)
                .filter(new Func1<Long, Boolean>() {
                    @Override
                    public Boolean call(Long aLong) {

                        if(aLong==1) return false;
                        if(aLong==2) return false;
                        if(aLong==3) return false; //發(fā)送0

                        if(aLong==6) return false;
                        if(aLong==7) return false; //不能發(fā)送5

                        if(aLong==11) return false;//發(fā)送 10
                        if(aLong==12) return false;
                        if(aLong==13) return false;
                        if(aLong==14) return false;
                        return true;
                    }
                })
                .map(new Func1<Long, Long>() {

                    @Override
                    public Long call(Long aLong) {
                        Log.d("debounce","發(fā)送了 "+aLong);
                        return aLong;
                    }
                })
                .debounce(3, TimeUnit.SECONDS)
                .subscribe(new Action1<Long>() {
                                @Override
                                public void call(Long aLong) {
                                    Log.d("debounce","aLong num = "+aLong);
                                }
                            });

運行結(jié)果

Debounce有另一種形式,使用一個Func1<?, Observable<?>>的函數(shù)來限制發(fā)送的數(shù)據(jù)告材。

來自bobo_wang的代碼

   Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
            .debounce(new Func1<Integer, Observable<Integer>>() {
                          @Override
                          public Observable<Integer> call(final Integer integer) {
                              return Observable.create(new Observable.OnSubscribe<Integer>() {
                                  @Override
                                  public void call(Subscriber<? super Integer> subscriber) {
                                      //如果%2==0坤次,則發(fā)射數(shù)據(jù)并調(diào)用了onCompleted結(jié)束,則不會被丟棄
                                      if (integer % 2 == 0 && !subscriber.isUnsubscribed()) {
                                          subscriber.onNext(integer);
                                          subscriber.onCompleted();
                                      }
                                  }
                              });
                          }
                      }).observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Integer>() {
                @Override
                public void call(Integer integer) {
                    Log.d("debounce","integer = "+integer);
                }
            });

輸出為
debounce:2
debounce:4
debounce:6
debounce:8
debounce:9

ThrottleWithTimeout則只有跟使用時間參數(shù)來限流的Debounce一樣的功能斥赋。

這兩個操作符的理解沒有那么容易缰猴,需要寫多幾個例子來加深自己的印象。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末疤剑,一起剝皮案震驚了整個濱河市滑绒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌隘膘,老刑警劉巖疑故,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異弯菊,居然都是意外死亡纵势,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門管钳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钦铁,“玉大人,你說我怎么就攤上這事才漆∨2埽” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵醇滥,是天一觀的道長黎比。 經(jīng)常有香客問我,道長腺办,這世上最難降的妖魔是什么焰手? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮怀喉,結(jié)果婚禮上书妻,老公的妹妹穿的比我還像新娘。我一直安慰自己躬拢,他們只是感情好躲履,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著聊闯,像睡著了一般工猜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上菱蔬,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天篷帅,我揣著相機與錄音史侣,去河邊找鬼。 笑死魏身,一個胖子當(dāng)著我的面吹牛惊橱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箭昵,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼税朴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了家制?” 一聲冷哼從身側(cè)響起正林,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颤殴,沒想到半個月后觅廓,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡诅病,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年哪亿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贤笆。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡蝇棉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芥永,到底是詐尸還是另有隱情篡殷,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布埋涧,位于F島的核電站板辽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏棘催。R本人自食惡果不足惜劲弦,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望醇坝。 院中可真熱鬧邑跪,春花似錦、人聲如沸呼猪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宋距。三九已至轴踱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谚赎,已是汗流浹背淫僻。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工诱篷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人雳灵。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓兴蒸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親细办。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

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

  • 注:只包含標(biāo)準(zhǔn)包中的操作符蕾殴,用于個人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,184評論 2 8
  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符笑撞。對于擴展包,由于使用率較低钓觉,如有需求茴肥,請讀者自行查閱文檔。 創(chuàng)...
    maplejaw_閱讀 45,600評論 8 93
  • 版權(quán)聲明:本文為小斑馬偉原創(chuàng)文章荡灾,轉(zhuǎn)載請注明出處瓤狐! 上篇簡單的闡述了響應(yīng)式編程的基本理論。這篇主要對響應(yīng)編程進行詳...
    ZebraWei閱讀 2,209評論 0 2
  • 注:只包含標(biāo)準(zhǔn)包中的操作符批幌,用于個人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 911評論 0 3
  • 響應(yīng)式編程簡介 響應(yīng)式編程是一種基于異步數(shù)據(jù)流概念的編程模式础锐。數(shù)據(jù)流就像一條河:它可以被觀測,被過濾荧缘,被操作皆警,或者...
    說碼解字閱讀 3,052評論 0 5