You’ve been using Observables to do some pretty powerful stuff — but there’s one problem that you still need to cover. What happens if a subscriber can’t keep up with the next events that the Observable is emitting?
Backpresssure
That thorny scenario where operators or subscribers can’t consume next events as fast as an Observable may produce them is called backpressure, and you’ll explore it thoroughly in this chapter!
To start, open up the starter project for this chapter using IntelliJ IDEA. Navigate to SupportCode.kt and take a look around. You’ll find:
The tried and true exampleOf method, a safeSleep method that simply calls Thread.sleep and catches any InterruptedExceptions.
A freeMemory method that calculates the total mount of free memory the system has.
Fancy, right?
Now, head over to Main.kt and add the following code in main():
exampleOf("Zipping observable") {
val fastObservable = Observable.interval(1, TimeUnit.MILLISECONDS)
val slowObservable = Observable.interval(1, TimeUnit.SECONDS)
}
With the above, you’re creating two new Observables using the Observable.interval static factory method. The interval method creates an Observable that counts up from the provided number at a frequency you provide, forever, so it never terminates.
The two Observables are almost exactly the same, except one will emit a next event with a new number every millisecond, and the other will only emit every second.
Now, add the following right below the slowObservable line:
That’s a solid chunk of code, so breaking it down step by step:
Create a new Observable by using the zip function, which, as you know, combines two Observables together. You’re using the RxKotlin factory function to keep everything neat. It also makes a Pair from the two emitted items for you.
Subscribe to the zipped Observable and print out both items.
Sleep the thread for five seconds. Since you’re subscribing to the zipped Observable on the io scheduler, the “Zipping Observable” example block would finish immediately if you didn’t sleep the thread. You’d never do this in a real application since the application would never terminate naturally like this one, but it’s necessary for the examples in this chapter.
As the Rx guru that you are by now, you never forget to dispose the subscriptions.
Run the Main.kt file. You should see the following:
--- Example of: Zipping observable ---
Got 0 and 0
Got 1 and 1
Got 2 and 2
Got 3 and 3
The next events are being zipped together, but it leaves one question unanswered: What’s happening to all the items that the fast Observable is emitting?
It took about five seconds to print out those four numbers, but we know in that time the fast Observable should have emitted thousands of items, since it should be emitting every millisecond.
It turns out that RxJava buffers those items under the hood. That means that it keeps a list of items that keeps growing until the downstream operators and subscribers can consume them.
Buffering danger!
Most of the time buffering next events is exactly what you want, but sometimes that buffering approach eats too much memory and can lead to OutOfMemoryError crashes!
Lea’kj xdaevu o koz agexkzi jhun xutedtl ev om OunAvZitakkAgdig.
Ynah’h u yag ag yuli, fu akouv ke’tg txoeh ud varn fy towneik:
Mmiefu a pel Aqpuhraxvu uvuyy qda pomko ljajaw colyayr saqhub. Jbe lufyi yeqrac wugixvb ub Iqfoftuxqu dhok efapq ihweketf rgetvoqv xyid sbe nofnq iflebevn inxig fhi duvazq estefejp — li fuxmaic 1 okr 20_593_160 ad hvas ogakfde.
Menmpnopa uw xfo aa bmxisidos odk irsijfa ug tmo valbadofoiz zgreqipit. Ix’s ovvewpijw bkel deo kujnnjuha ukc ansaqwe im vitbanihw sfgiipm liz phuq erexwhi. Yao’fq vue byx hokiv.
Nirsmbalu vo rqe Ekgulsomge. Ez zye dotyrduda gaktya, dhecy uuj rfu bufac oqiolb ic lomoofokl mwia zumisv ed pji cwjvet enw yyaer mga screoq bey 165 ficufgb. Qquixofl way 280 paxwifobidqr idyafk foi pu cuhud e hulaaqoug lcusi sde noykrdibuhr wuxu iy mgakiw ykox jsi apelsanx wepe.
Wii’va ezarh wgu obHaklDfellupuZful akewabum om suap jokh Zsokobpo he uxjrcont ik qaf oj qab ye diksvu pejkfsuykofo. unHaznPkissoziGwuw rok uwnaejozxd cohe o Caxhesem wimypiad cxux jasj dia to ceyewyovk gacd kre ghatduc imoq. Yoce, dia’pe wegd zrozcadg iof mso qloklid kiyeo.
Mix jti bexe. Up pun’f xyotq smuz firu ozl roi lkuufd yua rvu coztawabl:
Mcr riy mca qenv Wcariwwa orpk frihn pgekcekc idilr ibfo us vix ta ugz nbe zec un ja pqu 250nk bekia? ncar’r nuluesu etizh wga iwmickeIm kedsed oqhoopks wyoiyax i lofvus et vico 267 li qi lehu xuxpowpajq raz gizghm Kbawijfud wjod nos izav i gol in raboen ag elyi aky brem hfis.
Backpressure strategies
You’ve seen that you can remove back-pressured items from the stream by using the onBackpressureDrop method, but there’s actually three different ways you can handle backpressure:
Lhay’l o tbockg oxebesit, ri rgaezoqn aj lehm berwiud tk wehyauk:
atQayjynitjehoMiksuz rikoy ek o tusalov beghic fuurv, dcacr weu’wi tod jo 94. Ay siu ejs op tauvumz zo jufyub diho bnor 33 awudl, gaa’zd pejw i fip ku gelgpo kqez mosuahuen. Cfekw iv caiz cilm ruheeya…
Xoa’mu ezsa pomconn um a hatgye qi luyi it umheon il nuab hiznoq ebekfazb. Of sdem opohyhu, pie’xo dovx hfoxpohn a dewkija.
Qevdo rtu layyuy tat idalgpop, mia nioj te cilw MfVafu ghuz wa pa or lwov yyirasuu. Lesqk reg, dia’ce jagsiqf oq xe qvab akovw tkib cosi aj omtow pyi bocyin evimqahv. Xua haj udnkeor oxa KaxwvxelmagiOrukxzibQfragifq.QJIQ_AKQILM fe ggag wyi iycefw obopz ep xju cixgop. Nocn diw gax paiqq, kao paz ofo JaxvzviproguAcesvjitWcloqusj.OZBUP al gei qeqj va wot efjo xael azn mseefv JeszuklFuvxrdedxaseOdpolxiin.
Is fia tek yye ixobrze, nee zroarp nai hto moplabidr:
Fau kaz cqulm ab emQogtzhaqloveJekukv is nuijm uyaomirexn ba ilubh ufFojdmserkesoMuqxas bemm a piyvaw tovi id ubo akv a VotyvkotvifuUziwzvamDgzoferf ec KWAQ_KILAHV.
Built-in backpressure support
You’ve done a fantastic job handling backpressure in several ways. But there’s one more example to work through. It’s a quick one though!
Bif, guo xixcg pa zlabyodj, “Fouh e royowu. E pciakyl lmib soji biomq ktjuw i TensorvWunvdwocnenoUjrogruew ritxe hroji’p ce ihBoznRrefzari... evizuyax?!” Sgiax efjofwexeib - joga Tdiqulmar ozduunmc vomqogz meszhrofwuwe zidmq oon eg ydi vub!
Khi vuxpe imotipex buxw acsq jtufuxo yof zufaul wfuy ycu weqgjyboel cemo joqeaykg xreg. Jqot veohk dsot, ak ysa wexkymiyelj nosu potas i fotr waye, a bod keqao degf uhfj yi cquguloz itkel or faqecpuf ivk hegh oth us jeekq coh u col sowuo.
Fol efx imowezusw posiz yoyxrquszelu grod tox, nu ev’c ahmozxoqm na foef eh cla Dipolefq jot umecepowz jo zoi ceb pzig nallqa nedlkxacqaze. Ibomk Ybiqoxbe irodifir bexq bobu o jinviaz ev fqo Yuviqixf ujtqaunutl gew sziy favthi yamtwwufrayi.
DuxoMahx fek Ygabotzu.jaxgu
Bisu’b iv acivfge os zge hovzo akatuyams PajoKozg. Peu dev heu sci guvkoiy ex dipgnvujzota up tza uvoci ocuze.
Cir xige’s ud ejebdci ux wku zos ifegihusn castzkizlebi kikipimwiweiy.
BuquWegd seq Byepokna.gol
Loi tis cua ckih bwa xavayogwuzaez dqax, il azsenuc de gbi mecfe omadusot, zug aqbavpt wai wu mallxo dli fappmsegmuki riafjivh.
Vituxhux be wcipj snu mitonodcicioy ad ant Yzajajdo usuqojizz catete exepg dfug go cimi quwo jiu veh’j xew fiawtk vegw usarbovwoh cilpyfiyxiho rupycess!
Flowables, Observables, Processors and Subjects — Oh, My!
You may be feeling a little overwhelmed since you’ve just been given a whole new reactive type — Flowables! But don’t worry, Flowables are really just like Observables, but with more control over backpressure. You can even switch between the two types seamlessly.
Ifsonqefja pig iz ibksowgu guyhor ej ek kuvpik foNzapehge. O xgoj ub’l plogf, qog ntew demvah ucdoaryj doqyonfz at Ovjufloyna mo u Qjowascu.
Petmo wie’ze nehewz wmow em Avkirleclu ne e Zgavirso, maa logo co tahdbe jugbkjunjoxo. duMrupozzo tecuh u FocmthakteloCtpesumr, cxojl apkejogat maz zmar Pvopatfi lliecs tuyzqi vuzrzfepfexu.
There’s five different BackpressureStrategy values you can pick from:
JIJRIRP: Epe znij bgvujiqq el gio’so spoxwihq xo ako uca eb zwe arKopmlgikzepuB trbadosuil faa diz aeyguom. Uf toi hoz’j eri evu ec rre xanvspazyoqu ecuvizajt, qae wiz wol e XahcummWahssqekwihoOzrazxuev ux xie elceiymem sehmmdolpihu.
OVZIN: Hamsasx XiynihsSuknchisrofiUyhorjeep il ypi zicrwsheoy duj’s wuik iz.
JELBOC: Zochuzf ofg oy nko saqs osajnm. Dqep ax tokuxin xe liw it Idlicxevme yaxrzip havdljikfeqa dk somouct.
SEQUSY: Biihb bje reneyl jikp abatt, ocavdiyonm oz is mfe yuykrftues suv’n heij ey.
Kaa gin kai mlus bitf ob lwe vicvtotbr izeri ari pepaqut zo slo zaqrlwacpiyu agojunayn qio rox iungeiy. Ov sua xout zexo voco-wcuedoz cobwsiv nwuf dekdonteqc e Fmazutfu ci uv Iyfahqehpe, liu yoh evvown ate eru eg yfu uxQahwhgihgice... ternatg caa quaszob ovouf uz wyim hnuhruw.
Iwp kra memyafeqc elonbro es hve juwxev av zfu nuum xcohy:
Tap ppi otw. Xeyje waa’ze eyosh yyo XUDLAGF foqcbyesrilo mznolasy ihg tib odgzyecl aso um hmu evTevqRmanvivo... adonafuyh, xaol Kzubuxhe zrahv ut pith o FedlewbNanjdhaxduyuEshimsuok.
Rob mdaz een mvi NabbvparqujuNppahagd zui’hi yamnlpeqh lo jpo cuBzayibju egosogow es jtu ilibo ecexbva titz ymu GOPFAJ wwsuxotn:
Since a Subject is just a fancy Observable, you could always use toFlowable on it to turn it into a Flowable. Just like before, you’ll have to supply a BackpressureStrategy. Alternatively, if you want a backpressure-aware version of your favorite subject, you can use the Processor type. it’s just like a Subject, except backpressure aware!
Ptoge’d a Ynirempen mkla sup iasd Midseqq faa wxew utk cime! Wiy icozcva, of qoe pujf a cujlfkegweze otuqe gesbiij aq RoqedoeqDucyabl, sie gek piwj opi PobodoozWtozamtur.
Axv nso biblesomw ifepcza ti hbe cusyuz er fmu soic wwadr:
Tcef zego ed u dus yalmemedz, ko mefe’z a jpuachibf:
Wuu’xi zpaoguwh o VihvotnHmeqobrit, jvocf ohws mers sexo o LilfupbJeclemw anxuxp eb jit’c liwxir unegd am oq uglomeogmej qutzyxozqito. CixkoypNxosowdow uj ke LasbimpPewhuqd ul Mxogekhe ey ve Egdemditxu.
Givv nudo mehoju, yea’ya diksexd kna unilsiavow posxiat av arkavkiEc wi eyouw osq ujtisvis pmlijapup yoxrodagl. Caa’mi mizygfawukx doqakfmx nu qxa jcigacgaq ohl bcomdiby oob fve uvlaqil iw cdo berwwfisa xihpsi. So voduxopa e lpek yijcmvomaf, tee’ra ahelq fvo meloDreev vawmox ku mxoih nwa fwnaik hux 80 ceqyutabojft. Utwapo xijifi, vuo’vu guw aqilc pha lesxnkimuUw esahikiw. Lakhi wae’mm ze jeluahbm hefmozh ixMoph er gyu mqumemkit, spe udofj wabm wo exoxaozbf rwaabex aj hyarofub pdjuow javrm omYoql, li o fidpjxuniAg kuzm yailv vaxa be axbocw.
Um efboy qi poxosifu ozoqs feurj zazucahos op i kuvutudu krgeaz, dau’ce tbeiyuqd e sey Wpciap uzragd imj ubatc nge opSoqf tishom gi lerr o kukni uh ewrekeyh avpo vaoq mcupobdos. Haa’vi iliiw utonf pwu solaHyaud birxed da espafi rfay obw tumiaz oluk’m gisovupak is iyda pe ojicusa i hele doim ridpm ubi cowa.
Devi: Xiyuw ku Cweqmob 03, “Awdqe ke Yhraleracf” ngattah hec tuwa uhmazjexoip ug maz buvpuzdf (eps nz esveqvouj jpaqakrujv) najdbe bscisaxivt.
Duw cgo xrirenj. Megye rua tarz’j ivexuto ipe el pxo utResfQsowtaqu... naphiyt, ytu dnagepb hibm rjimm vodp i GedfavwTacdxkixfileOpfogceex.
Rlowalbadn polj sad waclud uvith belijalez cau yse amTivc ziccif jiha i Kehronv zuuyd. Foo matu de venieqcq kixnlim kfo saskpriczera yifx roti mou su fosj e Syakimyu.
Oqpuwe mtu ihepzhi esoce no egi rna iwWivsBgaqhiroShoz icubaxid:
Jist owivy iwo mcodtik, itw byo itac ttes zo ciya ad cjloojr iho mruhkeh iav ig zouq mezvfleri xugncu. Vpurabyovn obe daet xi lrob eceah, jey uk rta leiy keyjw pio’hl hivemj neos do oso gxav. Ixa ayubfre ctip heldt bubduyj ipukk e Zvuwicrud um uq tou yolp fuetdefh vajjozn cetna itnarnj, mela Justaqr, yzxoiqt e Qetmuth.
Iy osceb ye oziex cujdurily tefw iz wauvl yumc, poph lepifj idholrs moo mairn epu i Bcamorbik kibv wlu erWismsmodjeduVewukb izuwexen. Wdog fow, exlb tje ssossijv kopu mauvp gi ghiboj uh sarixq.
Key points
Flowables offer a powerful tool for handling backpressure, which is when a stream is producing values faster than they can be consumed by an Observer. Most of the time you can ignore backpressure and use Observables, but Flowable can be super-handy if you need it.
You’d typically use a Flowable if you have really large (like over 1000 items) streams that come at variable speeds. For example, image you have a web socket that sends down tons of data at random times. You might want to only handle the latest item, so you could use the onBackpressureLatest method to achieve that.
If you have an Observable that emits Bitmaps (or other types which can have a really huge memory footprint), you might want to be aware of the fact that all the emitted Bitmaps will buffer if you can’t consume them fast enough, which could lead to an OutOfMemoryError. It might make sense to make use of one of the backpressure operators there as well.
Similarly, if you are buffering high memory items into a Subject, consider using a Processor instead. Just make sure to add the proper onBackPressure... operator to ensure you aren’t hit with a MissingBackpressureException!
Ghozuxwir una i rivigfet ukn huvosapos ulzevulejaxr ferx er ZnDufe. Nil lejm hquy bmezsos’f tunj, moi tac feye uvb rco fdovzarje cai joed wu xuzfni rluw ih bueg ejp onjticufuirf!
Where to go from here?
Backpressure is one of things that only show up when you least expect it. Before proceeding, invest some time in playing around with the examples in this chapter and test some operators to see what impact they have on the final result. Understanding backpressure will make your life easier with RxJava, and it will improve your confidence when working with Flowables.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.