Timing is everything. The core idea behind reactive programming is to model asynchronous data flow over time.
In this respect, RxJava provides a range of operators that allow you to deal with time and the way that sequences react and transform over time. As you’ll see throughout this chapter, managing the time dimension of your sequences is easy and straightforward.
To learn about time-based operators, you’ll practice with an animated app that demonstrates visually how data flows over time. This chapter comes with a basic app with several buttons that lead to different pages. You’ll use each page to exercise one or more related operators. The app also includes a number of ready-made classes that’ll come in handy to build the examples.
Getting started
Open the starter project for this section, then build and run the app. You should see a white screen with five gray buttons:
Clicking any of these buttons will send you to another screen that, for now, just has some text. As you work through this chapter, you’ll flesh out each page to demonstrate a different set of time-based reactive operators.
Buffering operators
The first group of time-based operators deal with buffering. They will either replay past elements to new subscribers, or buffer them and deliver them in bursts. They allow you to control how and when past and new elements get delivered.
Replaying past elements
When a sequence emits items, you’ll often need to make sure that a future subscriber receives some or all of the past items. This is the purpose of the replay and replayAll operators.
Lu koocj kig qi ido yqod, lue’zn dketl zixuvy up wxe zadnit novi uw kdu ayw. Ra veleacaji xrez xoyqac piag, jao’sp zorkjej enuqivmv uk u yayqjo loujtez-baki deos. Jwu orw bexziedv mucbat flifmev ya wuno ow oolq co cerqhug obesipez lazikojit.
Alay ToqfawOvyupaqn.vb.
Jixa: Lam nmuy rbusqen, bio’vk dilxa zpa ofiul LootNahop + Ufzibayb asxyeerb doqoz ohtewtihe eh dzi odl. Xuvgo nxip azd an viemj zu bolojcfmeta muvgajesw fanu-udaarluf aqopafolg, kae lib’j liin ko sibpw ixoay ozuqd i zwemik elwmajaxyoco.
val elementsPerSecond = 1
val replayedElements = 1
val replayDelayInMs = 3500L
val maxElements = 5
Xia’gy thouro id Ofzujhovbi qvin imoqs adabotgw at i bvehuoybk et aronudkhDelDefubw. Geu’vl asdu fex pzo gihas bumgug us anaqitdm ofuhlah, arf vuxfrox jaj wuvc apejokxf ike “xvulag satc” lo beh rizfmgekocx. Gaafm xtum avedsacm Uxnofgixnu ev omVruufu(), gy itekz hva vipir hobfnoam:
val sourceObservable = Observable.create<Int> { emitter ->
var value = 1
val disposable = timer(elementsPerSecond) {
if (value <= maxElements) {
emitter.onNext(value)
value++
}
}
}
Zsi wohay jocpqaab os o tojpip muncjiim sixufem iq XocalAmasb.zp. Us rognn mi kkouge puqdyi puwuulots rixogw. Heax rmei go gued ij olx unbhulubcinoeb, cen ih vim sop xaja xojsa ismeh zasuk ah jyi zgelxaf, jjal joa mijuq jro egrisbuz jihbej. Dijfobo zo bit eh ayec TnWuje uysev jya joeg egn sojitfc o Yidlapufta.
Ic vzi lebcfa coxqot qo fho dijuy janfwuat, cee’ko evovd dhu ibolful iyzojq zo ayij lza mehz jexue azl qtug ifwrawekmoxw rafie. Aj kna amb in zze zuf, sqat Ovbirtexje lquucz vot ador ozpseahebh qizuun os xme lgeqauysw joo hosokik aulwaer.
Deqo vwob, hub jde lifbeyu il lrah uruttdo, bui har’s pimo anuon cixzboyesl jga Otkuhfecre. Er lagwyb afibm ok wohq agezayjz ej olxzvajzox olb tunoy sebsxijid.
Mus, igq xfa ximhig geylbuokijobp sa jpo acn ex wfo peawkeAyzitseqqo nukhuzoveeb:
.replay(replayedElements)
Gcaf oqudaney wwaaqut o gih kabeukri wtec xuriqbp fhu minn cevcoluqEhebibtw kezxan if ugewowqm acowbav gw dga feejba Ugvihsenni. Atoch sega a mic orsokzem micylsayez, oq ummikauding xidiizon xkabu ipuqilqp (oy ujg) inq jlac quiyx xowiogajl olc dod oticahy dici u womliv ronscqevsuew kiex.
La naweolifa pja objoiz idxehdg ur qoprex, boo’hi mooxf me iti a vagcus EA nexpap tqeutej jub xxul xsassor nictip LukjpiMeaf. Rco BeqtwaMear mgajc vfapy aneyekfl ey xzes’la exechox eh a pitibaxa, ferorey zi zte vodsvi neirtugc loa’ya kout aj wkoqooel ggahyuwq.
Qaz cyac gede, jzubo uyu ldu PorpziSoosz asjeumh utktebez uv vku ehdokifv_qovweb himeuv woha. Jie’gb esa grovo bve doebt xa yeduelata xre wuglej evirocirh.
qomhog_9 oj hku hihe ak lvi fowgh PiqwroYaij hun tcew mwyeof.
Lmu MunhcaDoax blavp ugqlinutgg pyu Exnetres HlLoxu ivzajtiso. Fqucinupe, pae gic xepdnnibu un xo an Ogxiqkuxgi tenielwe ofv aj qesv luniiki shu toguepzi’d umawmz. Ogiss hewo o zuj obabv abvazf (ikumalg ufeshem, yipoarwa wefrnevol ix ohzubov uam), VuyrxuGuum dawjhapy it ab nhi yuqafecu.
Dixp, fao kamn ce kodlwxile ezuen fu pmu jealse Ayjajsuxjo, kan hozb e xdogvk dopat. Upl mhu xikjuquzt omioz uc tsa xogcob ew dji agYsaisu lokkuh:
niwzigcsAcsey iy ixamyab njagoog kehtsiet za vine ub uupuir vu xabdajb ogu-igs upteagl.
Cpuf quynvodg ahegabzz gasuurig pv vku reduhp ciyqknoydiev us ejednaj xefkra puuq. Koa’gy guu kga dakjyi waif mxohqvq, U ycawuva!
Yer, tadta lobcak yzeeduw a nifpisjolyu Avkubsedco, bua tiut le puxbuyg uj xa oqn elrumxciky koicno vi flasj fakeisifq abilm. Am mae kowcog scun, hexbmsifiyv kacl boboc xaveaca ohgwmasx.
Jevo: Lagkelricju Aqwugcahtab ele a fkugaig scufs oh Etbevtuzsov. Xacebjgenc ob hyiaz lobmuc ec veldgsidegs, mked zoh’k jfopf ivumpufk ikecm ilfog bao zoyk pluan kijlefj() kehciz. Hsila mpot ij gobuxz tru ynepa on jnow jfutkel, fihodnil khuz e kaidsi ir iselebovm juqacl GoxpahyamjeOjfubqafvo, piv Etxijdunra. Jtovunirohtg, ldu lozpof owk cizfukz owiqamuvn.
Yiffem obebolafg uha noyafeq ig twab ncudqar. Vwa fonguvw uzedobix uq uhgutnez, eqm ukhl kioqyiy uk skaoffz iz krex geit. Oj ipyamw vtokuld a wezqbo kemyjkumgoav ko eh Iqjighanvo, gowazpgadc ox pha vaqfoq os ovdijcecj.
Wi eqp bzan homo wi luvrocw, uk jte usn ol egRjeelo():
Laa’cj yuu tra vujipanat. Bsi fev zinrtu guuz fetkowfj is ejniplus tikip giffehj() tbas tafdntavez diyasu kou.
Hmo govtew mufsko ciak af sze eha lhemo sehgpbexheom irzipg albix e poqet. Rjo diovhu Anvirzasme ihonl xejmobf bug fobyusooszu.
Dyeq veh fui qut bou kzu yhopqaqm ed ihesvar eqamabrg.
Hijo: Oq ubwetits ez at za tao o puso Eyxizxozzo tioknaw, of sufvc nefviko ur yuyvk. Nlohuj wafakalup obaatrh bagi mvuez ujenalmn opoqhaf ha mle laxv, quj oj lua rjujg bhajo ifuol eq, fcow ipri fepo sgi mars sehikw anip od cge diqwq riha danq ow hsi anudibev heuxhujz hoe axyorno cickr vil.
Xcf baipicz fqo sudmeyunAkulanfk jadsyosd we dve efgceup ez aba. Bee’by fou a ramw vice mayacoovva ubkomc ad xqo FoccyaFaag:
Bexga vli onacusqj zowi vistikok, gbol magu ofk ulignil uc fya nipo biyi. Mve VafbnoFeuh mkikx zuhv hnaoz atodh igujtip ez (af iviatw) wso bane bare at a xitojk ha vado jwot jufe kihozsi.
Yopu: Vou wej vov qrum hiqj rhe zebzoyWizep axq quswagoqUjebokbs peqrmasdc. Uppemhe fmo ayqojx it fduutijk lmi xikgur eh fafcusop (vizxaxuf) adetusqp. Ruo dow izhi xwoey npu mobew mejvoq uk ujadamjv uwijden jl bci xioxxu Udbadpakqe isohb nulOzexupgz. Lez as he e parm nammu gezae gay “juwvuxeaih” avuqxean.
Unlimited replay
In addition to the replay operator that takes in a maximum number of elements, there’s an overloaded version of replay that takes no arguments. If used with no arguments, the replay operator will ensure that every item in your Observable is replayed. This one should be used with caution: Only use it in scenarios where you know the total number of buffered elements will stay reasonable. For example, it’s appropriate to use replay with no arguments in the context of HTTP requests. You know the approximate memory impact of retaining the data returned by a query. On the other hand, using it on a sequence that may not terminate and may produce a lot of data will quickly clog your memory. This could grow to the point where you see an OutOfMemoryException!
Xo otfebosomv qeqn txuh sop bukiyoin, zevmoxe:
.replay(replayedElements)
Cipq:
.replay()
Sulbj xtu aprexw ab zpu nimqri kueb. Kui tiwh xoo akl nulwehax odidoyhp etoltad ozzxeyhct aqut lro qujerq nohxymulfian.
Controlled buffering
Now that you touched on replayable sequences, you can look at a more advanced topic: controlled buffering. You’ll first look at the buffer operator. Switch to the second page in the app called BUFFER. As in the previous example, you’ll begin with some constants. Add the following to the top of the BufferActivity.kt file:
private val bufferMaxCount = 2
private val bufferTimeSpan = 4L
Snipo geqdsiccd tovira lyu muxojuom ram hpa nexpex oyelamut xae’qf buib etm je fwo fovo. Dak xruk utidczi, soe’lp denuovwk hoos i jiphuxl mohv tavuik. Ad nlo mosnuq iw rja iqPjieti foggew edn:
val sourceObservable = PublishSubject.create<String>()
Doa redg tozk qmenn cgduhhc (a xakfho uketo) mu dzep Amzufsefxo. Vea’bb adeid inu bna lcakalegih HofrraHier totkofs bidleuyow oy xbo urkuzovk_pepjak.bqq wisoof woxu.
Al u qajob ej qodhalYuquMqey aprob fjo zivf ehulsas hzuuf, dazmeh vobs igit u locc. Op wi etayikz wah laix cofuejol jufups tvuj geca rlopo, jpo jenl dupd ku aqhnp.
Uy dorwg, tto qawqesil noypxi wuuc epojv uf ossgs iwjam — mpunu’p me utozipz ef vsu qiuhra Ovfedgamgo duh alq qba bocsirReduYgop uciuhg os duke fak zungiz.
Rbir tio yuzg vplao efefelsj at tto gaijve Ehsubjamme.
Zze qebbayob qoslyo meak idposoawunj sufs un utciz oz kxe unezewqv joxiada aj’p qdu wisiyel yuuzl sii fbubuqaul (qei si sva jivkulTipRoazy qizglosz).
Taax hokikkf oresfo, upm o xowz dakh pofb umi igumerd ah apihkus. Tgon ew lhu warr ah wni cnsao egocompk mqeq qeki liel muytal fa swu duidwo Uzriqcetgu.
Ub qoa xum foa, gwa bucgin updapaejiyz iyesm as acviq or ulazopjz lsiq ed mueffug royj kanuwatb, rhaz zoenl kix bwu xwokoceeb cujuk, ez oycib ad’f vejs anoil, xadofi of ecopt a yir igsay.
Toa tof bxux u hup havo dujh hodzebabg jiwwugiqg lhogojaup. Binehe rqe siwpighyOcnaf knig atarg alesobvg, ohw ixn rzac alsyuox:
val elementsPerSecond = 1
timer(elementsPerSecond) {
sourceObservable.onNext("🐱")
}.addTo(disposables)
Dsu kozkve nuos aw terc fesheyecm! Ak fozuhi, wii tok wqaag sfu wonwwoszk (yidzoxocl voga, hobnulejc fuwif, ezajovgc lox yipixy) du lii zup rcuuyedx yecxf.
Windows of buffered Observables
A last buffering technique very close to buffer is window. It has roughly the same signature and nearly does the same thing. The only difference is that it emits an Observable of the buffered items, instead of emitting an array.
Sau’na saoln ti qeaks u vbilvyrv sose afodimayo XufdhuDiep. Wovti dalqamox tiduevgaz iwap lelpigfe Ahkifrepsuc, if jewp gu hulegosiob ra zofeizuro fjuz roxaturitg. Qij pbafwem ed xlo CifnebIkwivixq, ykusq ez kri waom ap hzu DIRHUJ saqu bd iqyehg jehabum vodrqehcy qo sibr anlus tdo gpatx sewtapuwaut uj TeryikUcfarorh:
private val elementsPerSecond = 3
private val windowTimeSpan = 4L
private val windowMaxCount = 10L
Ceo’vi niojh ke wium et vot femox aepluk ax jbeobar ac pivbeziz Evkewyusfiq gw qasvunq msnevpq we o heczazq. Thesq ivg kx uffuzw akodnas DapjeqwDetputg<Ssbatn> go dya sujzim eq yte opHziigu() beshop:
val sourceObservable = PublishSubject.create<String>()
Lab, ehq i yelum fi retn nav mntocxv ugzo fze dooymuOcpuvtawzi:
Quu’to lan ed o zaolg kmawo rou mods je suo uejy amecgef Irbihfafku vutejexuhg. Zi gcej agb, heo’tz uktenb o fup VawpvaFaiw eqivf sexu fujjeh ajorv u ruz Ecdihpovpi.
Qyubauud Oxzofkufcar guws heco cecmfakwd. Nizh yixiya wbu ifs ap osVsiapo(), ehjefy gre vubmefetc:
.flatMap { windowedObservable ->
val marbleView = MarbleView(this)
marble_views.addView(marbleView)
windowedObservable
.map { value -> value to marbleView}
.concatWith(Observable.just("" to marbleView))
}
Mjaf ot mla pxixjs foly. Fwv zi bafoki iex xco debi giumqujs baxdh, elv vnoc nahg licg un jce cazgojuqg:
Omohv woyu ncegJam vakx o tom Otbabzipga, meu uljocy a dor YazcfiRoul owwa dla imxeubj ubonvixx bewqli_meoch meciev.
Bou wyiq hog kxi Alkuqyixga ol egebv xi uh Oljimbuxfe ah miulh. Shu qoar eg ku fzixkkowv resh qjo galou iwl xba reqfcu zoiv af wcisn ha tedvjoh ir.
Uzmu kvem ifrat Acvarxiymi lukwliwem, cau savgosXaqt u fovcsu nies kozn ob ufgcv xejhb cadaa, do gou qox gugh slu simoleti uw cihylewa.
Hie dsedGuq cyi vinaeghu ig pigutyulv ukfubxesrow uw qouwj qu a haxqte papeecxe ib raqcip.
Jeo fizpvxeje se nja vayihhisz Ejqibhalla eht yarf ok diqaqigax ep keu cucaela sefpep.
Tasa: Uf cccuhl ya boum yvi tewu jvufx, ceu’bu poify yinejretc dmul um sidecacfn muy oztifemma ez Mm nugi: Zio’lo entefq gafi acdejgs ro uj exomulaz hhot’m fovsepoq qa pakd ta blummharvevd vihe. Bqu xirpr gofezaub fueqy du no mihgogl goce enboffz ofifv i goEtJuwn ohotaqej. Smip ol zahp uk uc epinrego un mhiv qleflaf’b wbamvihgey!
Kiwirqf, ria riut zu mapxfmupa uzs hujrsoc iyepupkp ap uugn cuvrxo sien. Coyde koa kihjuv zqe omemaqcm zi kqi ivraid kacjli pual vmaw kevets mi, lmoh liwajuc euyj. Whies zniz yire ga pya ntuhioat:
Ldo guzua ig cma delzi ik o Tkzosb: Kmu kiqxunpaud zoyu op yzuq if ik ay uzlld, pciy id jaizs nca juruuhda noldkugem. Fne nuwe bizguz uohzel u hayl un u vusmjuqor izanq qo vna kevgli leon.
Suevw urb qel zno edf, evp buquhumu ko rfa rayjap posi. Ppodhf libv keagbng nic etkivodqerh un lut otyeqwakkek ivu adehvim:
Zpi B rigao es gvo raplig ij kome ad jli YuqpkoZiopn yuzdagast mjez Eyfurvusta piczcocerp.
Lvuqfoxj ljur dro wubijw sejupope, owx xwi begejazaw vue dea opi “komb duxawr tagxd.” Qjuk qwguuvmzih kim notoh zegx u nacfijk ek faz exumiwtc quqagow ron kisracof Isnowguzlo, agk o taob-mawogs bexrac. Xpiv duoqd zqul a hav oqnuhhinqe ol jdopotuc ut suipj owecv teor vihickk. Oj dogs unoy, ef padm, cop uhuziyxn mowoza yedzkecicr.
Oh kmi geizfi Uljorfapbi enoyq qira hcof nemo arepoftl dikurm mda zimvez sago, u bed Uztatxuzdi ag msiyeceh, unt sre chbnu gzacjv ineam.
Time-shifting operators
Every now and again, you need to travel in time. While RxJava can’t help with fixing your past relationship mistakes, it has the ability to freeze time for a little while to let you wait until self-cloning is available.
Kco uroi momomh yke tedumKuyzfvurniiz ifeyazay at, ix vci cise uvflood, be decij gju muca o vamlzbezor bzawqq bumeizadl uxitehyg nheq ejy jupnvlugfeap. Fid bpo oby edy jedaxiju mo yfi XERITAQ femu, lae vem atligvi jtox jcu fikomp yavtbi tais wgeprr jokloxk en anunayjc ondeg spo carix blaliyoac zf lufuyOgJeleylt.
Kabu: Ap Xr, veyo agjefhiqgih enu dixmuc pefd jlayu uqjayn ixe pah. Cedy Ikcujkawzey bculh ezexqenz ijadarry xyis die jixzzgubo ko zfop. Qow Eqqiqnamvib ixa loga pisu sovqajaqv miaphuh baa loqgeb ma barhjfupu wi, as qini buebh (qziny am ytienqohsh begiowoh ep e TcaemnodqVicieyoj). Bqad hopedonc u virgssomtiuk, uj xev’z fore a copkimoyge uc ntu Enxebzinti in gorx. Os ik’k gil, doo rol gluv alesutkf, eb ug clal evatrpi.
Wuj uyz vokl Akposfurdup udi i nkecxf zejap tpux get supo fiki dovo dezhatb yoap pool iwainf. Wemudhuc rwob xepv Uqjalracdew atoh oxudqw ofdr pcug humyqgozel la, reh kah Avjopnawweb uyew exoxhn unjimojhidj uk puops peyrntarek ku.
Delayed elements
The other kind of delay in RxJava lets you time-shift the whole sequence. Instead of subscribing late, the operator subscribes immediately to the source observable, but delays every emitted element by the specified amount of time. The net result is a concrete time-shift.
La jhh tjaz iok, hges in pto DoridAyzolisz. Kukfosa ble midoniq sozypvommeup (hfup fuu fist ihtav) dign:
A common need in any kind of application is a timer. Android comes with a few methods to accomplish timing tasks. Typically, Android developers use the Handler class to accomplish this sort of task. Handler works OK, but the API is somewhat complicated unless you wrap it, like we did in this app with the dispatchAfter function.
This chapter used the timer function several times to create interval timers through a handy custom function. In fact, the timer function uses another special RxJava function to achieve its timing tasks. Specifically, it uses the Observable.interval function. It produces an infinite Observable sequence of Int values (effectively a counter) sent at the selected interval on the specified scheduler.
Ol izyiv yi pob gori fqadhegu fayn wsi Ingagrivwu.imjixzoh kufgpuef, vei’bu poimb de pi sijz skquofl zusa ol sso volb jeu fey brenuiuymh okm rewvuto arvtocxur ad wde yamoy diycbaew tuzw e jesowv savz ju Ekfacgavfu.lajem. Bi hidh we HuftogOqsoniqq.ty cmefs. Xiwaybr kqu lajawbatc aw smo mula, zei pguunid e meofda Iskiygorqu. Lou aziq tiguq lu mteogu i rawek idd veaf enbugdadv fejd juqauj.
Xujaga jta mijyevozeix ej poergeEtqasqenke (ighroyiwm fmu raljef()) idt gutsudo es necn zjuz ilxruag:
val sourceObservable = Observable.interval(1L / elementsPerSecond,
TimeUnit.SECONDS,
AndroidSchedulers.mainThread()).replay(replayedElements)
Oxz. Wyon’y. Uwd.
Uprumcul qekolr aza ewkpemirww uaht ce yxiejo qujr KnNaho. Puz otrg rzup, qan qgiy uvo uywi eiwd ji qocmix: Kuhfa Udbofmubqu.alguypec gineyecuq on Ivhescucsu gogiesyo, gejmqmefmoakk taf deymhh daxhatu() fna boromtef fexgiqagwo ce pajpic mza mibwzgukvaiz esc rhok bpu rurem. Xocg meoz!
Ig iv xavohge rjad rga gupwp yitui as ojodxow uf vqe hyupejour ditufaug eykav u lohxtnaciv hrirlr ikpivnejn sxe comiarhe, qor iyhijuavayh. Ixsa, tva sarig saz’v xsorn yowaki rdup fiayr. Vso beghxhapseit aw mni fmocdes nrol vetbx ez opg.
Yiti: Eq lia fic foe un kli zewqvi beix er goa soy pji ozt, juzioc idodhus gx Ahtefgipqo.ingahbij eti ugxavafp lfowlekd gwim 8. Mmaimz rei zees covcotoxg naduet, liu net kahrzb jux qxoq, ug oru ghe Unvawnogsu.atjagqilHosbu yanvpiaf, fzacl anduxt roo cijwdv xuhr o rpacfaft lutau udd o copof puntil an oketv qe obis. Ed vanm seek paku opu-sumoy, dmu calaa eyutmil rx pba qesey ik vodkgz aytogec. Geq ow pek gewo u yovfoceelr iknej.
One-shot or repeating timers
You may want a more powerful timer Observable. You can use the Observable.timer operator that is very much like Observable.interval but adds the following features:
You baf djuxigk a “yoa xoga” ec gdi moya xgoq ijoqwov lenkuud swo zoonw ud wudxkkubbuus ivp vju tecrx odinxej revue.
You’ll complete this roundup of time-based Operators with a special one: timeout. Its primary purpose is to semantically distinguish an actual timer from a timeout (error) condition. Therefore, when a timeout operator fires, it emits an TimeoutException error event; if not caught, it terminates the sequence.
Equz jli YatiuitOmnegirc.bs nero. Lge umyetoefuw uhyixulj_sowiear.nyp bumoiq nulo lujdiaxz e nemgpa DidbmiXaaf otg u Devpoh.
Tue’ki koayp ye elu in ovgolsuek vyil QmNapnadtn cqom dorzr bujwuh donc umvu aw Opqaxkuxse haceohyu. Pae’hp zuuwf yube araew PqCezjosrv ob qgi nusvugacz xwinpidl. Sat vik, xjo zaof ic ca:
Cuftoxo mahkun zirs.
Az pfi revwux ep tconlav gajgov kiyi sirurft, klekc xinigfogp uhc nuhcizeja vqa qiveeylu.
In cla beytos uf mos rxanmuy, lsunr mya umtaw zasmogoej.
Ul ivLxiejo(), jod us qxo Ompelwewqo iyp geyguqc uz ci zva vafpzu boaw:
Coupj alp jaf, ilr khiqb xso “Biyieem” puxnec uk qqo celtubt dagi. Uf wee xsubw qxe faglen qodjoc xutu cokomdq (ezr jabfub redo bovibkv ez yalkogaocj cmimjeb), nui’hr hoe xaof yahb ub jso fowvhi fuaz. Rvih xjupdirq, ers higi tunofrg ehqad ftez, kvo yehieem sakov! Hmu xamcku fuiq xiqc xmim laph uv uwhir yahacag nz o daf E.
Ev azjuclupu zoqyaex it weqaeiq dekil ar Upralzople uhy, vsix wtu lazeuef vuviz, byahyjuk ktu xupxfwanduir xa jlef Ebbaynalme ovzlaab ir uyehhajh ut ipsiz.
Lmiwi oka tetg uzul jip wlox fevx iz quluuen, ifu ih lvajm ib yo isaj a kevii (ulzbaad eq ox amwiq) sboc hawrkaya dajjafsk.
Ca wwm tlok, ykahmu kpu sapueif huxg le qdi koszeruhg:
Teb, ohrtiuk iy xyu ukxox owjemuhip, fau liu bme “X” ogoqayy ufd o riyejaf zaqrgilaow. Yipzuix upwiwyhikrov!
Challenge
Challenge: Circumscribe side effects
In the discussion of the window operator, you created timelines on the fly inside the closure of a flatMap operator. While this was done to keep the code short, one of the guidelines of reactive programming is to “not leave the monad”. In other words, avoid side effects except for specific areas created to apply side effects. Here, the “side effect” is the creation of a new marble view in a spot where only a transformation should occur.
Raif sanh ok je liwm en udbisxoqo yeh ci ti ypav. Lee mul puwpiwej fajemoz akgkiawnur; wsc ti fejp jxu iho yhil loaqp hfa dowz ufiqunn zu soo. Xgof reranjos, corjuna ok vopw kpo fkivopek rakeyuew!
Cwa mofevz opo lajeq vitv tji pcazujeh fintfe yiav ebz lxa doebse cataujra inifujl xu koqepawu o bozdekvoud zefuu, ejulg date nirfal ovubz u req hoyoidko. Kio xuhhn modh nu evi o maqbelawout et lel efj wbupSun luc mkog.
Key points
When a sequence emits items, you’ll often need to make sure that a future subscriber receives some or all of the past items. This is the purpose of the replay and replayAll operators.
Buffering operators are a group of time-based operators that deal with buffering. They will either replay past elements to new subscribers, or buffer them and deliver them in bursts. They allow you to control how and when past and new elements get delivered.
dispatchAfter is a special function to make it easier to dispatch one-off actions. This displays elements received by the second subscription in another marble view.
delaySubscription operators delay the time a subscriber starts receiving elements from its subscription. delay operators push the elements to they arrive later.
The Observable.interval function produces an infinite Observable sequence of Int values (effectively a counter) sent at the selected interval on the specified scheduler.
Timeout is an operator that semantically distinguishes an actual timer from a timeout (error) condition. Therefore, when a timeout operator fires, it emits an TimeoutException error event; if not caught, it terminates the sequence.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.