[譯] RxJava 的全面介紹:Observable 類型病游、背壓衷戈、錯誤處理

原文:https://www.ericdecanini.com/2019/01/07/comprehensive-introduction-to-rxjava-observable-types-backpressure-and-error-handling/
作者:https://www.ericdecanini.com/about/

前言

RxJava 是一個不斷更新的工具庫狭吼,適用于除 Android 以外的許多平臺的開發(fā)人員(如:RxSwift)。RxJava 最大的優(yōu)勢是 以不使用回調(diào)的方式處理異步操作脱惰。

相反,ObservablesObservers 結(jié)合使用來發(fā)射數(shù)據(jù)(一次或多次)窿春,并且還可以通過各自包含的方法來處理每次數(shù)據(jù)發(fā)射時要做的事情拉一。

什么是 Observable 和 Observer

val myObservable = Observable.just(1, 2, 3)
 
val myObserver = myObservable.subscribe { receivedNumber ->
    Log.d(LOG_TAG, "Received Number $receivedNumber")
}

Observable – 發(fā)射數(shù)據(jù)流并與接受改數(shù)據(jù)的 Observer 一起工作的對象。
Observer – 訂閱一個 Observable 讓它開始發(fā)射數(shù)據(jù)旧乞,并處理接受數(shù)據(jù)時要做的事情蔚润。

在上面的例子中,Observable.just(1, 2, 3) 將按照順序發(fā)射整數(shù) 1, 2, 3尺栖。 Observer 一旦訂閱 Observable嫡纠,將以相同的順序接受這些數(shù)字。

Received Number 1
Received Number 2
Received Number 3

Observable 的生命周期

Observable 有兩個重要的方法延赌,來處理傳入的數(shù)據(jù)除盏。

  • onNext - 每當發(fā)射新數(shù)據(jù)時調(diào)用,正如你在上面示例中的 lambda 函數(shù)看到的一樣(在 subscribe 之后調(diào)用)挫以。

  • onComplete - 在沒有更多數(shù)據(jù)發(fā)射時調(diào)用者蠕。顧名思義,數(shù)據(jù)流完全發(fā)射完畢掐松。

不同類型的 Observable

最基本的 Observable 會發(fā)射連續(xù)的數(shù)據(jù)流踱侣,直到調(diào)用 onComplete 為止,這并不總是你想要的大磺。你可能想發(fā)射 單個值抡句,或者發(fā)射一個 無法接受該值的值,亦或是 在執(zhí)行沒有返回值的異步任務(wù)后調(diào)用其他函數(shù)杠愧。

val mySingle = Single.just(1)
val singleObserver = mySingle.subscribe { data ->
    Log.d(LOG_TAG, "Received $data")
}
 
val myMaybe = Maybe.empty<Int>()
val maybeObserver = myMaybe
        .defaultIfEmpty(1)
        .subscribe { data ->
            Log.d(LOG_TAG, "Received $data")
        }
 
val myCompletable = Completable.complete()
val completableObserver = myCompletable
        .subscribe {
            Log.d(LOG_TAG, "Task completed")
        }

Single 僅發(fā)射一個值待榔。onNext 只調(diào)用一次,并且onComplete 將立即被調(diào)用流济。

Mayble 發(fā)射一個或零個值究抓,當發(fā)射零個值時猾担,將跳過 onNext 并立即調(diào)用 onComplete〈滔拢可以使用 defalutIfEmpyty 函數(shù)發(fā)射默認值绑嘹。

Completable 不發(fā)射任何值,你可以像沒有返回值的回調(diào)一樣訂閱它橘茉。

Flowables 和背壓

還有一種類型的 Observable工腋,它就是 Flowable。和 Observable 一樣畅卓,Flowable 也發(fā)射連續(xù)的數(shù)據(jù)流擅腰,直到完成為止。但有一個關(guān)鍵的區(qū)別:

想象一下翁潘,上游 Observable 數(shù)據(jù)發(fā)射的速度趁冈,大于下游 Observer 處理數(shù)據(jù)的速度,這就是 背壓拜马。在大部分情況下渗勘,將會導(dǎo)致錯誤發(fā)生。Flowable 是一種包含背壓策略的 Observable俩莽,具有當背壓發(fā)生時驹暑,如何處理數(shù)據(jù)的能力岭洲。

val myFlowable = Observable.range(1, 100000).toFlowable(BackpressureStrategy.DROP)
val flowableObserver = myFlowable.subscribe {data ->
    Log.d(LOG_TAG, "Received $data")
}

有 5 種不同的背壓策略逊谋,我們需要了解下:

  • Buffer - 在內(nèi)存中緩存事件吧彪,直到 Observer 可以處理它們。默認情況下出刷,在錯誤發(fā)生之前璧疗,緩沖區(qū)的大小為 128 個 items∧俟辏可以修改緩沖區(qū)的大小病毡,但請注意,這將會帶來性能上的開銷屁柏。
  • Drop - 丟棄 Observer無法處理的事件啦膜。
  • Latest - 僅保留最新發(fā)射的值,直到 Observer 可以使用它并丟棄其它的值淌喻。
  • Error - 如果發(fā)生背壓僧家,將拋出異常。
  • Missing - 缺乏背壓策咯裸删,如果你想在客戶端處理背壓八拱,你可以使用它(因為背壓策咯是由 Observable 創(chuàng)建的)。未能說出策咯會在背壓下拋出異常。
Observable vs Flowable

已知的是肌稻,當你明確知道發(fā)射的數(shù)據(jù)清蚀,不會導(dǎo)致發(fā)生背壓。你應(yīng)當使用 Observable爹谭,而不是 Flowable枷邪。老實說,我還沒有發(fā)現(xiàn)使用
Flowable 的場景诺凡,也許 Flowables 將使用額外的內(nèi)存东揣?

錯誤處理

沒有任何代碼可以避免錯誤,你已經(jīng)知道腹泌,如果不處理背壓將導(dǎo)致錯誤發(fā)生嘶卧。最重要的是,在 Observersubscribe 方法中凉袱,由自己的代碼發(fā)生的異常芥吟,都將被視為由Observer 應(yīng)處理的錯誤。

高興的是专甩,RxJava 包含了幾種處理這些錯誤的方法钟鸵。

  • doOnError - 當錯誤發(fā)生,只需執(zhí)行該方法
val observer = myObservable
    .doOnError { Log.e(LOG_TAG, "ErrorOccurred") }
    .subscribe()
  • onErrorReturnItem - 如果發(fā)生錯誤配深,返回一個默認值
val observer = myObservable
    .onErrorReturnItem(0)
    .subscribe()
    }
  • onErrorReturn - 和 onErrorReturnItem 一樣携添,但接受一個返回所需數(shù)據(jù)類型的函數(shù)(對于動態(tài)默認值)
val observer = myObservable
        .onErrorReturn{ throwable -> throwable.message}
        .subscribe()
  • onErrorResumeNext - 如果發(fā)生錯誤嫁盲,則返回一個默認數(shù)據(jù)流篓叶,也可以為動態(tài)數(shù)據(jù)采取功能。
val observer = myObservable
        .onErrorResumeNext(Observable.just(2, 4, 6))
        .subscribe()
  • retry - 如果發(fā)生錯誤羞秤,嘗試重新訂閱 Observable缸托,你可以設(shè)置最多的重試次數(shù),或者設(shè)置空值以便無限次重試瘾蛋。
val observer = myObservable
        .retry(3)
        .subscribe()

你也可以通過布爾值俐镐,來實現(xiàn) 重試條件

val observer = myObservable
        .retry{ integer, throwable -> integer > 0 }
        .subscribe()

如果沒有使用上述的操作符哺哼,在錯誤發(fā)生時佩抹,將導(dǎo)致程序崩潰。

結(jié)語

到目前為止取董,此 博客 的大部分內(nèi)容都是關(guān)于 Firebase的棍苹。有充分的理由相信,Google 通過強大的 云數(shù)據(jù)庫 茵汰、機器學習云服務(wù)枢里,將推動 Firebase 成為最優(yōu)秀的云解決方案之一,并也為服務(wù)器開發(fā)打開了新的世界。

雖然我會回到 Firebase 上栏豺,但從現(xiàn)在開始彬碱,我將潛心學習 RxJava 并深入了解它的細節(jié)。因為它還有更多的閃光點待我去學習:修復(fù)回調(diào)地獄奥洼、提高行能巷疼、線程調(diào)度.....

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市溉卓,隨后出現(xiàn)的幾起案子皮迟,更是在濱河造成了極大的恐慌,老刑警劉巖桑寨,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伏尼,死亡現(xiàn)場離奇詭異,居然都是意外死亡尉尾,警方通過查閱死者的電腦和手機爆阶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沙咏,“玉大人辨图,你說我怎么就攤上這事≈辏” “怎么了故河?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吆豹。 經(jīng)常有香客問我鱼的,道長,這世上最難降的妖魔是什么痘煤? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任凑阶,我火速辦了婚禮,結(jié)果婚禮上衷快,老公的妹妹穿的比我還像新娘宙橱。我一直安慰自己,他們只是感情好蘸拔,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布师郑。 她就那樣靜靜地躺著,像睡著了一般调窍。 火紅的嫁衣襯著肌膚如雪宝冕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天陨晶,我揣著相機與錄音猬仁,去河邊找鬼帝璧。 笑死,一個胖子當著我的面吹牛湿刽,可吹牛的內(nèi)容都是我干的的烁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼诈闺,長吁一口氣:“原來是場噩夢啊……” “哼渴庆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雅镊,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤襟雷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后仁烹,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耸弄,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年卓缰,在試婚紗的時候發(fā)現(xiàn)自己被綠了计呈。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡征唬,死狀恐怖捌显,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情总寒,我是刑警寧澤扶歪,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站摄闸,受9級特大地震影響善镰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜贪薪,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一媳禁、第九天 我趴在偏房一處隱蔽的房頂上張望眠副。 院中可真熱鬧画切,春花似錦、人聲如沸囱怕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽娃弓。三九已至典格,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間台丛,已是汗流浹背耍缴。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工砾肺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人防嗡。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓变汪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蚁趁。 傳聞我的和親對象是個殘疾皇子裙盾,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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