RxJava——基礎(chǔ)學(xué)習(xí)(八)屿愚,錯(cuò)誤操作符

學(xué)習(xí)資料

錯(cuò)誤操作符不多川无,文檔上暫時(shí)是就兩種妇菱,但感覺蠻實(shí)用的承粤,但兩種操作符有好多種延伸

1. Retry重試

當(dāng)原始Observable_Ob遇到錯(cuò)誤時(shí)暴区,,接收到onError信號(hào)時(shí)辛臊,會(huì)重新訂閱Ob仙粱,直到能正常進(jìn)行操作終止,操作符默認(rèn)在trampoline調(diào)度器上執(zhí)行

repeat是接到onCompleted成功信號(hào)后,重復(fù)訂閱

retry是失敗后再次訂閱彻舰,repeat是成功后重復(fù)再來一遍

1.1 retry()

只要收到onError()的通知伐割,就會(huì)重新訂閱并發(fā)射原始Observable,無論多少次刃唤。

簡單使用:

    /**
     * 當(dāng)為4時(shí)隔心,制造一個(gè)異常,重新開始尚胞,就重復(fù)
     */
    private static void retry() {
        Observable
                .just(1, 2, 3, 4, 5)
                //將數(shù)據(jù)進(jìn)行變換 小于4就正常發(fā)送 
                .map((i) -> (i == 4) ? (i / 0) : (i))
                //出現(xiàn)異常硬霍,重復(fù)
                .retry()
                //對發(fā)送數(shù)據(jù)項(xiàng)進(jìn)行限制,就輸出10個(gè)笼裳,否則會(huì)無限輸出
                .limit(10)
                //將3個(gè)分一組须尚,緩存進(jìn)List,方便觀察結(jié)果
                .buffer(3)
                .subscribe(new Subscriber<List<Integer>>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println(e.getMessage());
                    }

                    @Override
                    public void onNext(List<Integer> integers) {
                        System.out.println(integers);
                    }
                });
    }

運(yùn)行結(jié)果:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1]
onCompleted

結(jié)束時(shí)侍咱,會(huì)得到onCompleted信號(hào),并不會(huì)得到異常信息


1.2 retry(long)

  • retry(count)

當(dāng)收到onError()的通知時(shí)密幔,最多重復(fù)進(jìn)行count次訂閱

簡單使用:

    /**
     * 出現(xiàn)異常楔脯,就重復(fù)訂閱5次
     */
    private static void retryCount() {
        Observable
                .just(1, 2, 3, 4, 5)
                //將數(shù)據(jù)進(jìn)行變換
                .map((i) -> (i == 4) ? (i / 0) : (i))
                //重復(fù)5次
                .retry(5)
                //3個(gè)數(shù)據(jù)一組
                .buffer(3)
                .subscribe(new Subscriber<List<Integer>>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println(e.getMessage());
                    }

                    @Override
                    public void onNext(List<Integer> integers) {
                        System.out.println(integers);
                    }
                });
    }

運(yùn)行結(jié)果:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
/ by zero

當(dāng)重復(fù)訂閱次數(shù)結(jié)束時(shí),如果異常仍然為解決胯甩,便會(huì)拋出異常昧廷,可以拿到異常的信息,不會(huì)得到onCompleted信號(hào)


1.3 retry(Func2)

傳入一個(gè)Func2偎箫,通過函數(shù)來控制更加定制化的重復(fù)訂閱

    /**
     * 傳入一個(gè)函數(shù)木柬,可以控制重復(fù)訂閱次數(shù)以及是否發(fā)送onError信號(hào)通知
     */
    private static void retryFunc() {
        Observable
                .just(1, 2, 3, 4, 5)
                //將數(shù)據(jù)進(jìn)行變換
                .map((i) -> (i == 4) ? (i / 0) : (i))
                .retry(new Func2<Integer, Throwable, Boolean>() {
                    //integer 已重復(fù)次數(shù)
                    //throwable 異常
                    @Override
                    public Boolean call(Integer integer, Throwable throwable) {
                        //System.out.println(integer + throwable.getMessage());
                        //返回結(jié)果 true 重復(fù)訂閱; false 淹办,不再訂閱眉枕,并將onError通知發(fā)送給訂閱者;null怜森,不再訂閱速挑,不接收onError通知
                        //重復(fù)次數(shù)小于5 就再次訂閱,超過5次副硅,就結(jié)束姥宝,不再訂閱
                        return integer<= 5 ? true :null;
                    }
                })
                .buffer(3)
                .subscribe(new Subscriber<List<Integer>>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println(e.getMessage());
                    }

                    @Override
                    public void onNext(List<Integer> integers) {
                        System.out.println(integers);
                    }
                });
    }

運(yùn)行結(jié)果:

[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]

1.4 retryWhen

學(xué)習(xí)資料:

retryWhenretry功能類似,都是在接到 onError信號(hào)通知的時(shí)候進(jìn)行重新訂閱恐疲,默認(rèn)在trampoline調(diào)度器上執(zhí)行

retryWhen會(huì)將作為onError信號(hào)的Throwable傳遞給一個(gè)函數(shù)腊满,函數(shù)會(huì)返回一個(gè)新的Observable套么,新的Observable發(fā)送出一個(gè)數(shù)據(jù)項(xiàng),retryWhen就會(huì)重新訂閱原始的Observable碳蛋;如果新的Observable發(fā)出了onError信號(hào)胚泌,則不再重新訂閱

retryWhen

簡單使用:

    /**
     * 出現(xiàn)異常時(shí),重復(fù)訂閱5次疮蹦,并延遲 2 ^ integer 秒訂閱
     */
    private static void retryWhen() {
        Observable
                .just(1, 2, 3, 4, 5)
                .map((i) -> (i == 4) ? (i / 0) : (i))
                .retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
                    @Override
                    public Observable<?> call(Observable<? extends Throwable> observable) {
                        return observable
                                .zipWith(Observable.range(1, 5), new Func2<Throwable, Integer, Integer>() {
                                    @Override
                                    public Integer call(Throwable throwable, Integer i) {
                                        System.out.println(i + " -- " + throwable.getMessage());
                                        return i;
                                    }
                                })
                                .flatMap(new Func1<Integer, Observable<?>>() {
                                    @Override
                                    public Observable<?> call(Integer integer) {
                                        //System.out.println(Math.pow(2, integer));
                                        return Observable
                                                .timer((long) Math.pow(2, integer), TimeUnit.SECONDS, Schedulers.immediate());
                                    }
                                });
                    }
                })
                .buffer(3)
                .subscribe(new Subscriber<List<Integer>>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println(e.getMessage());
                    }

                    @Override
                    public void onNext(List<Integer> integers) {
                        System.out.println(integers);
                    }
                });
    }

運(yùn)行結(jié)果:

1 -- / by zero
[1, 2, 3]
2 -- / by zero
[1, 2, 3]
3 -- / by zero
[1, 2, 3]
4 -- / by zero
[1, 2, 3]
5 -- / by zero
onCompleted

在小鄧子大神博客最后提到一個(gè)二進(jìn)制指數(shù)退避算法诸迟,Math.pow(2, integer),延遲2^integer秒愕乎,重復(fù)訂閱次數(shù)越多阵苇,延遲就越久

算法規(guī)則:

  1. 對每個(gè)數(shù)據(jù)幀,當(dāng)?shù)谝淮伟l(fā)生沖突時(shí)感论,設(shè)置一個(gè)參數(shù)L=2
  2. 退避間隔取1到L個(gè)時(shí)間片中的一個(gè)隨機(jī)數(shù)绅项,一個(gè)時(shí)間片等于兩個(gè)節(jié)點(diǎn)之間最大傳播時(shí)延的兩倍
  3. 當(dāng)數(shù)據(jù)幀再次發(fā)生沖突,則將參量L加倍
  4. 設(shè)置一個(gè)最大重傳次數(shù)比肄,超過該次數(shù)快耿,則不再重傳,并報(bào)告出錯(cuò)

二進(jìn)制指數(shù)退避算法是按后進(jìn)先出的次序控制的芳绩,即未發(fā)生沖突或很少發(fā)生沖突的數(shù)據(jù)幀掀亥,具有優(yōu)先發(fā)送的概率;而發(fā)生過多次沖突的數(shù)據(jù)幀妥色,發(fā)送成功的概率就更小

每個(gè)字都認(rèn)識(shí)搪花,組在一起,不懂嘹害,先記下來撮竿,知道有這么個(gè)玩意


2. Catch

操作符攔截原始ObservableonError通知,將onError通知替換為其它的數(shù)據(jù)項(xiàng)或數(shù)據(jù)序列笔呀,讓產(chǎn)生的Observable能夠正常終止或者根本不終止

2.1 onErrorReturn

在接到onError錯(cuò)誤通知時(shí)幢踏,發(fā)送一個(gè)特殊的數(shù)據(jù)項(xiàng)后立即正常結(jié)束

簡單使用:

    /**
     * 出現(xiàn)異常時(shí),返回10
     */
    private static void catchReturnf() {
        Observable
                .just(1, 2, 3, 4, 5)
                .map((i) -> (i == 4) ? (i / 0) : (i))
                .onErrorReturn(new Func1<Throwable, Integer>() {
                    @Override
                    public Integer call(Throwable throwable) {
                        return 10;
                    }
                })
                .buffer(3)
                .subscribe(System.out::println);
    }

運(yùn)行結(jié)果:

[1, 2, 3]
[10]

2.2 onErrorResumeNext

原始Observable遇到錯(cuò)誤發(fā)送onError關(guān)閉信號(hào)時(shí)许师,通過一個(gè)函數(shù)創(chuàng)建一個(gè)新的Observable

簡單使用:

    /**
     * 遇到異常時(shí)房蝉,發(fā)送一個(gè)新的Observable的數(shù)據(jù)項(xiàng)
     */
    private static void catchErrorNext() {
        Observable
                .just(1, 2, 3, 4, 5)
                .map((i) -> (i == 4) ? (i / 0) : (i))
                .onErrorResumeNext(new Func1<Throwable, Observable<? extends Integer>>() {
                    @Override
                    public Observable<? extends Integer> call(Throwable throwable) {
                        return Observable.just(6,7,8,9);
                    }
                })
                .buffer(3)
                .subscribe(System.out::println);
    }

運(yùn)行結(jié)果:

[1, 2, 3]
[6, 7, 8]
[9]

2.3 onExceptionResumeNext

在接到onError錯(cuò)誤信號(hào)Throwable_T時(shí)進(jìn)行判斷:

  • T是一個(gè)Exception異常 不是一個(gè)錯(cuò)誤就會(huì)啟用onExceptionResumeNext新生成的備用Obsvable
  • T是一個(gè)Error錯(cuò)誤,則將這個(gè)錯(cuò)誤發(fā)送到訂閱者的onError()方法微渠,不會(huì)使用新生成的備用Observable

簡單使用:

    /**
     * 異常時(shí)惨驶,啟用備用Observable
     */
    private static void catchExceptionNext() {
        Observable
                .just(1, 2, 3, 4, 5)
                .map((i) -> (i == 4) ? (i / 0) : (i))
                .onExceptionResumeNext(Observable.just(6,7,8))
                .buffer(3)
                .subscribe(System.out::println);
    }

運(yùn)行結(jié)果:

[1, 2, 3]
[6, 7, 8]

3. 最后

重點(diǎn)是retryWhen的理解,在處理一些過期token時(shí)敛助,會(huì)用到粗卜。我們的項(xiàng)目中原本token有效期為半個(gè)小時(shí),后來改成了一個(gè)星期纳击,還沒具體實(shí)踐過

本人很菜续扔,有錯(cuò)誤請指出

共勉 :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攻臀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纱昧,更是在濱河造成了極大的恐慌刨啸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件识脆,死亡現(xiàn)場離奇詭異设联,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)灼捂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門离例,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人悉稠,你說我怎么就攤上這事宫蛆。” “怎么了的猛?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵耀盗,是天一觀的道長。 經(jīng)常有香客問我卦尊,道長力惯,這世上最難降的妖魔是什么宋梧? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任盈匾,我火速辦了婚禮捆昏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淌友。我一直安慰自己,他們只是感情好骇陈,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布震庭。 她就那樣靜靜地躺著,像睡著了一般你雌。 火紅的嫁衣襯著肌膚如雪器联。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天婿崭,我揣著相機(jī)與錄音拨拓,去河邊找鬼。 笑死氓栈,一個(gè)胖子當(dāng)著我的面吹牛渣磷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播授瘦,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼醋界,長吁一口氣:“原來是場噩夢啊……” “哼竟宋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起形纺,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤丘侠,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后逐样,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜗字,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脂新,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年挪捕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戏羽。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡担神,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出始花,到底是詐尸還是另有隱情妄讯,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布酷宵,位于F島的核電站亥贸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏浇垦。R本人自食惡果不足惜炕置,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望男韧。 院中可真熱鬧朴摊,春花似錦、人聲如沸此虑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朦前。三九已至介杆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間韭寸,已是汗流浹背春哨。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恩伺,地道東北人赴背。 一個(gè)月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親癞尚。 傳聞我的和親對象是個(gè)殘疾皇子耸三,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

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

  • 本篇文章介主要紹RxJava中操作符是以函數(shù)作為基本單位,與響應(yīng)式編程作為結(jié)合使用的浇揩,對什么是操作仪壮、操作符都有哪些...
    嘎啦果安卓獸閱讀 2,837評論 0 10
  • 作者: maplejaw本篇只解析標(biāo)準(zhǔn)包中的操作符。對于擴(kuò)展包胳徽,由于使用率較低积锅,如有需求,請讀者自行查閱文檔养盗。 創(chuàng)...
    maplejaw_閱讀 45,600評論 8 93
  • 注:只包含標(biāo)準(zhǔn)包中的操作符缚陷,用于個(gè)人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 911評論 0 3
  • 創(chuàng)建操作 用于創(chuàng)建Observable的操作符Create通過調(diào)用觀察者的方法從頭創(chuàng)建一個(gè)ObservableEm...
    rkua閱讀 1,801評論 0 1
  • 注:只包含標(biāo)準(zhǔn)包中的操作符,用于個(gè)人學(xué)習(xí)及備忘參考博客:http://blog.csdn.net/maplejaw...
    小白要超神閱讀 2,184評論 2 8