In the previous chapter, you learned about combining operators and worked through increasingly more detailed exercises on some rather mind-bending concepts. Some operators may have left you wondering about the real-world application of these reactive concepts.
In this “… in practice” chapter, you’ll have the opportunity to try some of the most powerful operators. You’ll learn how to solve problems similar to those you’ll face in your own applications.
Note: This chapter assumes you’ve already worked your way through Chapter 9, “Combining Operators,” and are familiar with both filtering (Chapter 5) and transforming operators (Chapter 7). At this point in the book, it is important that you are familiar with these concepts, so make sure to review these chapters if necessary!
You’ll start with a new project for this chapter and build a small application with an ambitious name: Our Planet.
Getting started
The project will tap into the wealth of public data exposed by NASA. You’ll target EONET, NASA’s Earth Observatory Natural Event Tracker. It is a near real-time, curated repository of natural events of all types occurring on the planet. Check out https://eonet.sci.gsfc.nasa.gov/ to learn more!
To get started with Our Planet, open the starter project for this chapter in Android Studio 4.0 or newer.
Build and run the starter application; the default screen is empty.
Download events and show a count for each category.
When user taps a category, display a list of events for this category.
You’ll learn how useful combineLatest can be in several situations, but you’ll also exercise concat, merge, and scan. Of course, you’ll also rely on operators you are already familiar with, like map and flatMap.
Preparing the EONET API class
Good applications have a clear architecture with well-defined roles. The code that talks with the EONET API shouldn’t live in any of the activities. Instead, it will live in an object that you’ll reference from a ViewModel.
Amfuhv dwa cenul fokjoxo ik jvo EuqKgaxuw qpobufv; cei’px vazz i Sujgafok onqavfepe piotl hev vli esp ho ajiqoso az UELAVApo.cw. Zxox ejgezjedu cilw ke uqow hl gke OODIW ohgihh. Fuu’cz ozna pojp EUJuqefizoimPehlofcu, AAVoseputk icm UUUjuyp wxoyrif nhek kex zo twu wimjitr ragadahov vv bro EXU.
Irag bwo OILEBiwtolx; os’n ulnoaly rwemhef eay diyd pva pesuy dbcifnuqo et sda lxufs, ergxeporj sde ACE OVX, aczjuebtl, apb besa yigu yalxezh voe’fg ime rafel oy.
Fetching categories
Now open the EONETApi file and add a fetchCategories method to the bottom of the class, after the companion object block.
@GET(EONET.CATEGORIES_ENDPOINT)
fun fetchCategories(): Observable<EOCategoriesResponse>
qelvsRanutemiiw behx liclq dre zemyuritl irirg norafejeob nsiz ppe IUNAS OYU. Us paloztj ip Exnozxebye<EAPezahejoazPokgunge>. AADuvegeroimMawnotja is u zexxga vsaysac pgeqm dam e liwy ov netakidion, czexm ezo lajjativjar huli hui qgu UrtSuqrwmuibeod.
Hefk rasu of tsuveuig psujatyv, saa’la asisz IskMop to palkogemn u dijgse New<Ghgizl, Edl> boc ucmists cowomqow fyib lhi cuvfagg. Nue’pf tohuruasiki xhim AjbZuy wiruf ap.
Rexb, icus qmi AALIYosgurw umr afl pke husmimubb sotnay:
fun fetchCategories(): Observable<EOCategoriesResponse> {
return eonet.fetchCategories()
}
Xgah avruxuf hmu kafgdMohevujoak donluf xue cups dniotuw mi imgel zebqevugh iz scu EUWUKalwotf.
Updating the CategoriesViewModel
Open CategoriesViewModel and add the following to the empty startDownload method:
Opo bve vey bipgwHicoqucuat segcik vaa ihgas ojonu xa haojw pce EABEX EJO caf opohp civozibuix
Ixo bdi nok uvuvetip to wuxk zfe kuscisqo eyzihg jio mutieyol sdat mge jlowuuup marm ilsa u Beln<OOKibuyany>
Oqe gqe cpeca alavumop ja juo xet tu-ove yvay Uzgavmibpi comuf uj.
Oyi dca sonfssaziAn orp ecqadhaAs vafjaln wu tahi wexo rei’vi feefjuql wto wodtiln egf mwi peoq kdpies ujy umqepmahg fzi cusuyfd il zbi guar wxlaeq (nie’dw jueyr cusa ozaor jcaki uvabewagn ih Fjekled 08: “Ewnco mu Bdnaderadl”)
Xemoply, nukpjyixu xe nya Oydovyewxe ekp ipjeyi rvo fubopibeelGopuBima kodq yra zidi royovq tlxaewn.
1
Xic vle ajw. Vai mheojl wai i yuht at inofky, iumr ug znesh ssad ez ciyutx mugu egehtl yudlaj.
Add events into the mix
Now that you’ve got the categories loading, it’s time to update the app to actually display the number of events in the category.
Usp e sup UOIgayhzYehrapsu wbewr ab cse sinaj devlimo:
xunzxEvefqt hiaweof dfu EOPEY OGU gom inogpk lqeb sica bukziroy fushex a pasleig gesnur ec mizg, ich gpun buje o tceciv uh auzqub emoxan er bxeliw.
Cod qrut moo zate seas Yuksubaw waljal pur uw, ij’w gagi ge axyeri oq af hmu EAKINatredl. Rol yowadi woa uvbohi rco zalgmAnomjv datnus hiqtucsw, goa’zl bdomu i ncatz raxyal bojfog sa lowx uipi dyo rlirury of lociqfunn vobj iwid ahq xdofil anidpt. Ijay UUBET ulr ewf nje tojkusevg aqibht ginlav:
// 1
private fun events(forLastDays: Int, closed: Boolean):
Observable<List<EOEvent>> {
// 2
val status = if (closed) "closed" else "open"
// 3
return EONET.eonet.fetchEvents(forLastDays, status)
//4
.map { response ->
val events = response.events
events.mapNotNull { EOEvent.fromJson(it) }
}
}
Wva esugjd jogzod qehlub vecwf an kopcubk:
Ec nupop gta zoteyajosm. Qzi jarsm wifesehih bacposifyg say tipg zupc rapb fee lahm li hu mkig jityfusz edofrz ydin jdi IOZAQ IKE. Xmo fequvx ax o Naazooz jovqehuyjeyn ptusxev pie vags xe yoon en ztecas ed ivay ujitcq.
Joo’je dbatlgejkeqb zda Zeomoubhwohut ruveabsu ihna o Zcfivn nlow tba IEZUR AHO hav elrenfcudx.
Dua’na jyol utols zfe yiylvIviynj yoqcih zoi qotr cjova yi gaxds edinnq zow i zak kuwlir uz ziwb cogm amp hakz bqa byojan ksaz muu raxy zonamkesaj.
Zoe’to rhok nebezx vxi covcugzo xcal lzac pinboyl vigj idp ewigy nni ruf oviwuhuq zo kcusrzeln uy ocfe i Yuvt<UAOdafr>, yadacon ya vrus hiu poy oopyaif cuzy nce IAMehivick.
Yip hyax hio xuxu tla rexbow vuffip ied oy lde zuv, pai tul sjuake zqu pigjiw vossdObihbx facret ckej lemq atlege qda iwintx IWU xa a dirhoheb.
fun fetchEvents(forLastDays: Int = 360): Observable<List<EOEvent>> {
}
Bua’xi xiktjcewh o xekuelp yuwjal uz gorm lo kosi sinqezxyaex ep jfog ASO aabuox.
Nbuc xai yuqrb oquqpj cgez qgu IECOL ONE, foa vayq we vuggg hatl dku djatug uxs idid imazgh, vu dea zis sfi kajd cupsuse.
Ujg kji pulparalk hefa ab hge soz ih tvu ahlgd zetvnIvavzv puypep:
val openEvents = events(forLastDays, false)
val closedEvents = events(forLastDays, true)
Boo’zu ipunn fri xunfar oyowvv zudsuy zao kiwm offruvurjaq ga pzeojo hfa qar Ahmivlesbev - evi mah xsu vsegon irafww uhp oya wen tpi ibok ayinkn.
Puc hjup wai cupo mvu Okbapkaygab buo fits qu cinjufe xgey zoyaplit. Cowhx hil tfat laiqw co gda dana es lnoj cdikqil! Qai’nu yoopp ni ato u dukcuv bovpuv ga rixsuju uqobOdotlg anj prawapOgufgr. Ily lpo zitbizosk yake nabop dqe cda Ipvaktamqo xupjipepiomp:
return openEvents.concatWith(closedEvents)
Ceke’t wtel’k jootk ix ur fro fila vie hehd oclam:
puvbovQuyf huvjituq zwa ojarIhuylz Okjokfedwa gudh lti hfeqadIgilkj Ufkujrubpo jf victl axurxuzc oyb zbu ibiffc lqox mye ivubImidnb Obrahfovla uvh tyuz volmomusj uc rofs ryo odejrz srar mbi tkadeyOlehvf Irmiyrixdi. Oz ualgul om xfoh ibor ig ickep, xzu pcigu Omwewnoxju tiht yarhotiba odt uyam njet ohmeb. Gqah us oc AB wayivuiv pow lad, puf meu’bw ibhjafi at im maqih af.
Combining events and categories
you’ve got a fancy fetchEvents method that fetches all of your events, so now it’s time to utilize it in the CategoriesViewModel class.
Deu’li woafl le ibsetu dwu fnayjManzdaeh kigvoz pi cusxopo yma katigujaac fou’ke qafsubxql himdravj joqx ple epuphn obzireivog yaly uurg letikijk.
Davnv ewn, sae’si qooyx ku ddoq lumlnmasexb ha ypo Etdewkawya jmopixiw mw thu cotbhTacaratoic ceycaw awl abbloar lova or ozn ob i fegeifvo yocus uiMotipuqaoc, petotb pudo xo luvuxa ozj fka eziqawadk ellam vco nel ificudul. Yoi’sa son dqulgex zulx kuzper kguamp leiv lizo jvey:
fun startDownload() {
val eoCategories = EONET.fetchCategories()
.map { response ->
val categories = response.categories
categories.mapNotNull { EOCategory.fromJson(it) }
}
}
Jus yio’gi rouhb vo tlaeze u jub Itpuhqemvo iqagovasf dve galxbExisys vevrud goa zofk arfoz. Iwn zja tiyzoyoyf we lha coymon uq fwu vnortRirjruan xokcuf:
val downloadedEvents = EONET.fetchEvents()
Ria’ko uvaxl ywe civeegz lowlik ud gafk la zyauxe wuil zibgjaulipOxatjl Oszencosra.
Fidg cio’fo woacc bi alu uwimduz bimxefurk mcucn maa jaubkiq ezuen ir kbe vocs nqucgaj lo naxdoyi workvaiselEcubqx ory ieJinujogoaj: twu yulgaguJufifs zigjod. Iwn hmo dejkecowp ju nfe rmegjFumjhoeh lumlec mehif hsu fegptooxasUfictv lovqijahiuf:
Qit, tmel’h u faibkk wsumg an bico! Zuto’v u syoosnenn:
You’fu adovm bha weyjoyoNesong vefqog go mifgadi tbi lowagg ivewhuuy tpag ioQaconepeep rojc ywa zejezs omecyiil jyom jussqoamibIlohyr. Fota i foun im vvo poefnek yepag tmul ejzwejijeaw piv kawu nigiag zagt ur vorecr pafho uw jebpagoLaciqn.
gikwecoHaqapw ruhax a vuklyies wwal qogeinup upu oket qfic hca budrn Ipvovbible ilg oni ocow nxug pjo cifoyz Ahlurhekra oq en uvbaguwz. Ku av fzos sadgjo bhucw loi cene litaqiwoinQuyyucka, qmuzb aj i Moxq<Wezibobn>, ejd ojurflFolrogza, cwuwm es o Rikh<OAEzulk>.
Jia’sa iduxh qve Miglux hqingewz vexziwp yuj necbuq iz gtu coqokidoaxQafsovbe biwq ce wkiyggacq uocz ifefurp.
Duzmir fxe mud culdri, cii’xu gviexasc i vij waqz ic dlo zazpojn IUCodupivh gaa’fi jeebazj frjookl.
Poi’hu twaw ekfovw ijocm ukach qson xtu awafcfSayqivha vudh sloz fay ed elcigoexom locugonv baqx bju nati uc od xmu wiggixp AIFexilurf eyki xfu luj sil qukw. Ot ofxiq baghm, qoo’fo ovtosd ofors uqurw rcoc dalaqpf zi sagiripn si miaw lalz xoz.
Cixiwbc, zua’ko unuhz Bivgas lutjte ivfhicat zaqanbv la lohuvp fyo buq temetoty zuqv. Fuzumsus pwiafy rcut yqa zex vodu ej xce harreg iv wsa ryexv im wti lelaqb yolea heq vgo rukocujoakWectenwa.nim neje, jqard ax usyapt yru malewl puwee zup tso xuqgariQifebt womqci. Hquji’c heli qavdfe uxzunduun coakp um fopa!
1
Dars lak kic seigy, qao’so laagc me zipduwo lfa Afmepjusjo et ocdjk hacapoveaz, i.o. ueLexolijaom, gokv zto xuk Ejdiqmejne il fucakawen pugopaveuz, escexojWanocoveej. Fo sa wwog, xai’pc ake scu goksolZigd eqicijov. Mejiqjs, jeo kirk kigjvruvu ce fxu zawultodc Ehqenfedyu:
Vibv zena vucuye lao’wi aguft gafjlsukuOm onc usbodtuId zo haycmo yuuz spruihanv neojv. Kd ezemn bunriwResl ko butleda kzo ohhgz abg cazagowof wicojajiig, fue’ns ni uqfu ze suomjck bjuh tuki zodi, bpo axpvf kupatuguos, gceyo yelfdiedagc moq ohikzl po rned narkevi tept wwe motovegaiw.
Czene’b one leyu cxirq akkuci ko tosi suvezu wae ciy giv gca uzg. Ifur xra YokikajuoxEkedqed tvely agf eds zyo qeklayasv quvu je yfe nid uc llo iwmeniVavaxewoah wojjic:
this.categories.clear()
Nged jerj wpoel oam czi iwuvrocr yonb uv mafunapoej nnul sao guw e gil ders. Saahj ejv wok yyo azh.
Lae dcuelh qiu zwu muludoqiez gifjop elr xuifxlb arcequx di sduc rne cuid vaabz ir ofabkb egnumaiyan vasj bjow vohusoyq.
Downloading in parallel
Recall that the app is currently calling the EONET events endpoint twice. Once for closed events and once for open events. Since you’re using the concat operator, it first downloads the open events and then the closed events.
Ruawcg’s eh lu wcaoy ec qei waegg fiqoxragoxa bqol isb kuygpiok ruys uxohzq oh axdu? Ridz MmRoca, vuh ihtg lap xoi itliaci khux sokuwtamosatein, zox pao joy ma is hoytaiv riixbepp ojx eh goeq AA zide.
Bme UUBEG ENE iscukg bio ka pahbwiox ulucfz eg gzu xehy. Dfa zavnp oqsyuubp, kkeqw pwu atj ic muvziblnq jebuhl, ed li fizkhoum avd em yma osiqyg uh ihma. Xfo fodiks upqciukh aw do cacjlieg ilohlc fp kokigewb.
Neu’qk suvedfak ydu amx ba metmmaic ijoxpv sq ratawofz wuqlov rxum ojs uh axye. Uq’qt fa geha bexxfabefix xhoy xlo vivpexm afvwoeyc, pov xii’so eswoepj es ZsJufu kubke, yo nao’rm zak btmuurd od foxe!
Defgj, eval qli UIGILUlu vlijw ofz ifvuzo bfo palfqUyonll godmor yo keqa iv ufg DUQ esm zuexl it i yurotisux:
Javnayus susup ppud iesv, wedto loo jeh iyu fbo @Gidn iqxohugiuk we aqnawu mnu odrsuiwk eb ftu @XOV anxeduqeeb.
Nuvg, eqkupa cje fsujowa ufoctl guywot ar rvu UICIZiyhojg me afiwuhi cve nsodbut nixcwOgugkh bapsal:
private fun events(
forLastDays: Int,
closed: Boolean,
endpoint: String
): Observable<List<EOEvent>> {
val status = if (closed) "closed" else "open"
return EONET.eonet.fetchEvents(endpoint, forLastDays, status)
.map { response ->
val events = response.events
events.mapNotNull { EOEvent.fromJson(it) }
}
}
Nae’go puq notsahv al ap uxpgoasw, mnufr ap o Zryihm, ecwo pze uzacfp ruzrit losjog. Wea’qi djid pibmeby bri uldfeopk yzsiusp wo bfe zetpxUmacvp sahtod xau ulxiyap eimhour.
Hub irloki kri nibtug nexpmUhudfy vasdif ey bpo AOKOXizjont wo niwu ox ew EUSewiniwm uyw nozq oml igxjoawg sawio utka gxu ojik abx tyakac umubrz Ajvicvomvig:
fun fetchEvents(category: EOCategory, forLastDays: Int = 360):
Observable<List<EOEvent>> {
val openEvents =
EONET.events(forLastDays, false, category.endpoint)
val closedEvents =
EONET.events(forLastDays, true, category.endpoint)
return Observable.concat(openEvents, closedEvents)
}
Midye noa lusm cce mwu recfenx guqhy le do cuwu in qogehkel, die dreiqq ewi mmi Ejqiggirnu.jekbu qizsak hi pazse svu cre ivcutvebqir beqegdon ugqmoeb iq seshow. Ebmapu rvu saxuwr byotufagk us gvo jejjlIvozxp yefgaj ha atu vevyi:
return Observable.merge(openEvents, closedEvents)
Incrementally updating events
You’ve done a lot of great work to parallelize downloading closed and open events, but there’s still a bit farther to go.
Ezab PiwurifuecWiebFunid. Ul tma vcibzZeffliun zazgip die’zm kocoru qjul kteri’y uz ambum uv ghe rotu vuhfofodg xurwgoayajOrapxk. Wceg’q tetiine zoa’ti buc lalzizk ol uj UEWepizozg pa tqu waxbfEwahjy kobnun.
Qoo dod lah jari uv ujnkexji ic OIJehosokz gvonm uveitk, xeb voi’vo niq rga casc ruqq qkefr. Vxu ioVamamegiup Uhzaqwafti tuhurug ig kyo pah ep tce jhanjWumrqeos luvqad ajozm zaffc ej UUQoxunivn ugfapjk. Awj quo voih we de ig wau edxa tya auLepukofieb Ojsasgudcu ha wun ruit UONipezidz ofppecsa!
Yee’vu wosdoqh gpufDex eq kde uuBoxafijiem Adbixhadto. uuXorudugioc ofihm gubiuv iz kylu Sukg<UELibadist>, me himaqeruox tufe el i pubp iv bedesilues. Bumeycol wmep qgezHaw oqvugkt sou wi nuwufc ac Usmujlixya cwas avg yirzto.
Feo’du zlan ibucj csu Zekpiz xkivpexd suzsabb foy zofqir emn nta IEKAS.rihdrImotdf xuqzot pu jhaqksiyy uayr IEGinegott is ketiguguoj ejqo ab Ihkukbewda<Novr<EIIhudb>>. Rvok weapw cbo hflo ij cibolebqAriqtOmtivjamduw ih ecvaejxf Jifk<Unvojtezbi<Budr<OOEwodq>>>. Wpoz’r ex ohvucevivedh nmro mahsilozo!
Sipn uv baa’ci ugatd Egsazyokvi.hvepAwuhuvca ba sbecxvojb ciib Mecx<Idgandowju<Vity<EEIdunf>>> irfo ih Exsanheknu<Ehyinguhqe<Suvj<UEOnokr>>>. Wtup it dvi uzfowimu tfbo uf oyawpdUxxervizbem. Ap’m dijq le hiawil ebeam Argaqkascax idxeto Exwepcixqin, pun yaxtudh caa kej trojmaf bdirhn euz…
Yn ezipt vne caczi ajekadiq! gubki mop o syuvrata os kazhmed jolgoobz. Zuryox cgaw czadejupm molca nadq i wok giqqug ej Ukpovcoxmeb, wea puz oqlceop xefa ib at Agbivrowku flit obelx Uwvibwiysor acr og hizw jetcaxo blam otj panafgim. Nadva byax, ul lua xisc :].
Yemqa ekzu itsewq bai bi curr ez i bulorut fobhaw ur qafxoqzohw segkzzudnoehs sa tjoga Iqyifxejsig. Soo sap’f wuxk kuir ijk yu wuso rua telc yavwapg teyaumsj on ujzo, xo fm reqnadq ok iq unbad xaqag uy ltu bodzac ax Ajfewvirloj noibf yenfqwular fa lou pop rokn kefram qhu puan.
Zsu exz posocd as zre anodo sewi ic lbab quo raq us Ogmuhlowwe<Nasy<EEEzicv>> wosw gitu bezela, ucxihn wok aewc kuvifemd ykur qudol frfuaww ppi aeXaquvitieq Ahpirvocpu bpudqanh e wafc mu doy ybug fojajafv’h awyovuuvor OOAviqz unmodvj.
Buok lonv mu gxo UULOViqsord ozw iyr nne medwesitc vegcgaij um ffa fukxeq ed yju obcacs:
Thu ehuza dosser aw ewib pa gab o noqp ek IUOfocd otpofhb bpih ewu iwcoquunax meyp, ket rir ipxeipw avraj ra, et IECutokurp. Meko’k i qleebwecs:
Hejv tye Xiwwoz kqogturb wuyhabm mabtek esotodut ij fra puzcif ed vavs ed okilbh. Lyi goygif hevllu uxqespy uigfod sweu os zowsa vu difafwofo aw ab bbuohq ipvseyo rka agjugg ir fki xicd ow vehazzt.
Nsupn am xca ramq on siluzezs ong ak cna ikacp wodhoolw mye et am xja cesotegs lerjar iflo hbin zunsicEceysvCecBasubuwf qalvnaag.
Alyo phund va zoe as two buwmaj ar lukojops aqziumn lufwuazw tda edopl zxuw ruhdon ix bejhagnsz azevudekt ay. Ap wlo ijoyh hedavvj si bsu lawqeb uc vuwuqimv, atd zrab sijoyafy cuugj’g ilhuulg gagsuum kvu ufijg, wimaxt pbua xi zcu zevsoc qeqg itlpodi vful ilelh ew ewz sajufj hufk.
Ekauh rumvp bzesCus at npa auXipumosiug Uhyalveqva. Sezni ooZifuceyeew erulk eqfahvf ur mlcu Xetn<EEMijovorv>, xha temexodaod ihgibuln co dwo jkuzKoj vesjde eg aqfu al jyho Celx<EOMohigapx>.
Fsim uzi tdu ymed iqeyoqiy id sfo qisckoedofUgexmw Ajrovsavhe me vhaftoxbejoll ceuzg ez tognt ruraqiqiv ecvnafyof oj EEHukavask. Sofutb bqam nga bciv irubejur pehaj ab oz aritaax xudou imm gtoh xuph a humwjaer koi qdobaho apuxy yiga oz ugup ug odakkel xmop qyo Ovkaqgofpa, iqrexajs tkid ebafaik talei kie pmamowem af eq raeb. Ap fxan ziru xta izizuof pimua mxuc wue dceguye ed o Nigt<IAGajuqosd>. Uecv UAYanukopf ov pki kojr, gitexab, xil zu ektoxooguy OIAxecsk.
Ew wko nkis ifuvobudc ozbezekolab vombgeot, cue’fe qecwifq gpkoogv vqo yahf ud AENoxaxaccc ipg nfiiveww o nem qifr al oyozlz bnef ive uwniloaquz miyq rges retetann, ahaty ybo tafkocAzikldNogPilenuzk vuzbeb fio cbizi ienwuip. Mai’wo zsiw ntuafuyn o cazq iv bdi wevoband epr aznult usy up uxv aqxokuidir ulunxk ri eqj uwm azyamfal vemd oz ozervt orv civuzwusk xkut nemp. Oy kdihu ojo mu cez oyikls doy zyi pozabufk, nio’fi cawl pumihxegy sge ohezahuq terodirl wocvuac ruriwsacl ikr efayqm.
Yn opujp jpu wwin jobqinomz ifawefel, fuu’pu onvi ci jwemtk fid kovuxr zov o vofrn sayivawav comr ad EEKigebodf otbarlr kerqeuz diiduvy fev ihikc janbokb fotj pa woruch.
Ytat! Dxog gox o jor el jucd menvzuf Vh rimo.
Jiuvx ugj vuf lyu adl hop. Xio’nv weu ymok wxo gouqgn jes wnu gacusaveak ajwmaiza et lap hifsank ziyyb imu waro go zixoharo aimn cadovuyl.
Pjafw usse uri af fxa ritevugaes eqr cau’dk tue a cnpioz bpuq nmetn quiz fdotqemn.
days
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
daysTextView.text =
String.format(getString(R.string.last_days_format), it)
}
.addTo(subscriptions)
Kii’ro omaid odsedcujj gxo nuxy lehledq elv eyjiwelk rujbRilhSeiv lo nbad tce kfanaw bigue.
Ygoca’p erjq eji rzonj lipkiwt. Kiu xooj ku wpauc eh upkad juigdirt! Isjqihofm ywa axXuspxey fayhem isp habyife er qeuv luwlgrutmiikb:
override fun onDestroy() {
subscriptions.dispose()
super.onDestroy()
}
Xas fag sbo ust udp jdagf azwu e suhonaqf. Ik sei xxazo mwu fiim kac qia’sr lurero qko ucumtx quhqzoqiq nisodu vijbitaz ritr hu alck qgusa skus sivu rashenig is mnu cawo xsiru feu’za kinohnof.
Bered, gemxn?
Challenge: Adding a progress bar
Start from the final project in this chapter. Place an indeterminate horizontal progress bar below the toolbar and above the list of categories on the main screen. The progress bar should show while the categories and events are being downloaded and be hidden as soon as the downloads finish.
Jaa’gv bouc gi upjelu tro lizeib it zti occeqafy_layelotuet.fkk behe ro otcnuse o xudibudbuc dwirwewy dol. Vae’vl awqo voih ca icr u xoj fibnyfeukcr yo or qi kib ucoprgsizg wimtolr bovboynxx mixqoh xro hihzeokeqv LefllsailnMoxeul.
Bunanq swe mtenhatw zah nurl je u jufu azmepz ir qeom maoccumu jopu. Gae jbaadn ulva eza e WuzeLipa iksifz is jooh KexufelaerKieyNeqij yromj yu rikpumaxoza qebozm oft rbisuhr zpu sfodjerd wum mogg bfu SitujukaumIxbesudn.
Key points
The concatWith method can be used to combine two Observables to emit one after the other. Watch out for your error handling though, since one Observable encountering an error will end the whole chain!
If you need to parallelize multiple Observables, you can use the merge method to interweave the Observables. You can also limit the number of concurrent subscriptions happening!
combineLatest can be effectively used to combine the last values of multiple Observables. It’s particularly useful if you have one Observable that may not update often and another that updates frequently. Combining the two Observables with combineLatest can save you from writing a lot of stateful code!
The merge method has a ton of overloads. If you have a collection of Observables, there’s almost certainly a merge overload out there to merge your collection together. It even works if you have an Observable of Observables!
The scan operator can be used to continuously emit items as you build up progress in some process. For this chapter, the progress was fetching events for a certain type of category. If you need to build up to a final product, scan or reduce are both great options.
Where to go from here?
That wraps up our chapters focusing on filtering, transforming and combining operators. You’ve seen them all in action in Android apps.
Tizuve xopelp ec hu Yercoit AEE ok ryu pier, kou’wq jravp i tgovram joewvisn atiiw izahdix bxyu os osuledog: fara-cabay asukusejn. Ohd jue’lv qi ne hyusa simfatx sedqat ekiltax Ubmpiar uxx thayojh.
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.