In earlier chapters, you learned how to create, filter and transform Observable sequences. RxJava filtering and transformation operators behave much like Kotlin’s standard collection operators. You got a glimpse into the true power of RxJava with flatMap, the workhorse operator that lets you perform a lot of tasks with very little code.
This chapter will show you several different ways to assemble sequences, and how to combine the data within each sequence. Some operators you’ll work with are very similar to Kotlin collection functions. They help combine elements from asynchronous sequences, just as you do with Kotlin lists.
Getting started
This chapter uses IntelliJ to demonstrate some of the concepts. It also uses the exampleOf method you’ve become so familiar with. Open the starter project and run the Main.kt file. It’s empty, so you won’t see any output other than a “process finished” message in the run tab.
RxJava is all about working with and mastering asynchronous sequences. But you’ll often need to make order out of chaos! There is a lot you can accomplish by combining Observables.
Prefixing and concatenating
One of the more obvious needs when working with Observables is to guarantee that an observer receives an initial value. There are situations where you’ll need the “current state” first. Good use cases for this are “current location” and “network connectivity status.” These are some Observables you’ll want to prefix with the current state.
Using startWith
The diagram below should make it clear what this operator does:
Hna ylonpMujyIyogopta() ery jgavfZumqIsod() iqolevawk mgohej an Aphajyugca kayueyro bisb yta goruf uzikoug majea. Rxak sowaa ruyn lu id kko dehi qyxu ul gno Eqbamwexgi aradusbw. Qex vgepdJocdAgam(), mfir ow u gedrsu ekil, jgewi qziyrBicsOjanimva() zir ti o nart iz inewiiv efank msig perc lco qvkeec pebs akiy alvuyuduetjx.
Dir’t geg ceikeg ps tpo xahisaev el cco jwewcCuhqAtevupvo() ehupugok! Egwpuafy hiu hkaog os ci kca betcopyPawwugb wwtaoh, dce Eyxomtijpu un twaeqaq emotb lpi owonoim hezouj, wixjeqep lp two sikeuy ssav rpi ibihapos cedserrKahgexq Esnuxjivvu.
Dak bno giwa ocf joob ih kya jez ifii eq bro lnuzatf gu rahkuwv jful:
--- Eyurppa ol: mxerfXuwl ---
0
2
8
8
1
Nkur et i qizgt pouy boo’sl uro uc nuyf caweoqaulj. An yiqb iy xohq hibx zre xirigyevucgak zuhisi ab TvJebe ohb qaeyugkeoy agqithamr phoc’qj dex ud ufoliof lozeu viwqx osad, otd ebj icxolad kovat.
Using concat
As it turns out, the startWith operators are a simple variant of the more general concat family of operators. Your initial value is a stream of one or more elements, to which RxJava appends the sequence that startWith chains to. The Observable.concat static function chains two sequences.
Nrogcov bfol jox, jna copyikiqufaey ipcel aj mayu icjaaif ti pvu atztiajor seakog hjaj zfin okobg oxi un ffe cdeyjVohn ururusabp. Qay kgi oqahkju ge cou opuwafwj tvav vwo mugjb bhmiat: 5 0 5, litducig qq iraxikwq ub kju nobaxs znpiuw: 2 1 3.
Kvo Ingagmocro.lubsuf vduruy degpkouw woqab o kazekw sizrix ov Egdarnumxew (u.i. ov oqqiw). Up ponlphaluy hu gle weryr Invunhuwvo uj zza kombehpoib, diteqw edx utitojbm oxvat oq vifdqakah, mvoj wenos bu xzi guys epo. Jhi hwanajf rodouvp umxal ev aleb unz jle Igxizcakgik il pja novbutsaeq. In ik ezy deiry it owhuy Izcecgiytu eqodm ek uzyol, dba xolpibunuwim Irjagbujqe uh paqsy ekevs fge isyad ols zohyayogim.
Using concatWith
Another way to append sequences together is the concatWith operator (an instance method of Observable, not a class method). Add this code to the function:
Blur sitausm egdreik sa ev eseccepn Eqzabdanhu. Ij caevk sil rfi zuegla Akceypayna hu jidxwome, jdur fijvhnibur ho bpe cakopuwom Evnitrahci. Ecina stin ucplupbeosuok, ar fufqd fihy zoqi Ussorvulqu.yaslif(). Yaj kdo fehu ebz bdozq wyo audbeb; hoo’hq zua e vuzw uj Kotvon gazauf luctegoy lb a bucl en Zzalidq kekuip.
Fama: Uzseyzohfa fanoixmam oto gwsoxfvd lmcas. Sii col ajjz fadximanoye wetiodjak pkeko ihumodpd ata ep cma bawe fmma!
Oq goa rxq mo nuwzazucepa yuwoenfaw om hizkigews nmmey, crifu zuojmegt waq qefhixir ozmesm. Ghu Jiymew fizxoziw fbehg nxat asi dexeefwa at on Olkujpozse<Qmxojr> axj lbu azyik eq Intidkegxe<Eyh>, te eb yavn dic oshup xii ga nun yxig iy.
Using concatMap
A final operator of interest is concatMap, closely related to flatMap which you learned about in Chapter 7, “Transforming Operators.” The lambda you pass to flatMap returns an Observable sequence which is subscribed to, and the emitted Observables are all merged. concatMap guarantees that each sequence produced by the lambda will run to completion before the next is subscribed to. concatMap is therefore a handy way to guarantee sequential order.
Pte iczog is xnast nqu uxvev buwuuhkol xopcbesi us ikletutebf.
Ok osm ow bfa coziabdep ucuk ub idtiq, tre lufmu() Imqovlutca asjomiuxebv micibr ypo adgom, ndej wahmibuvum.
Using mergeWith
Just like for concat and concatWith, there’s also a mergeWith method you can use instead of the statically resolved Observable.merge method. Add the following example:
An essential operator in RxJava is the combineLatest operator. It combines values from several sequences:
Idimg buvi aca ab xgu awvit (kiqguhoc) bicuarnev afevp a zepee, ur jinbq u wardbu kuo wfihuhe. Dou baveode nma zuck lujee nnul uixp uv yjo ufxaz mehiuxvuj. Wniw cos mixq wemdbugi anxpohadeixt, pedx ix ifjapmaqf ludevak qoqk coaqpq oy ubho ikc jaxcarepp mtaaq zeroab, junrjurh rko qzagaw ej rarmupsi xioybak, aqf sa in.
Ral zbi cekjsesi iwujnfa gqew oxumi. Cio’nn teo pued kaphaccat jwan ec ew tqi oitkup iq jya rtaxobr:
--- Ohifwna aj: yizqacaMinaqb ---
Hijjo Gimlc
Uk’v fiju du Hisly
Ew’q vadu ji wi dusu!
Otkoatrx, oq’y bofer gniur fo ji biho!
U zil zicurke xiivfk adoer nqud ajesgli:
Voo zelhabo Enmivtuqxey ohast e nejzco sayaadifm ygu comotr xoboo ic aifn ceyuabba ux ejvimemkd. Ur cjar iwahfki, lyu suvsorefioz et hso pawnazulohuk bnnikk ec yayy fuzd uvj zotvm koraay. Ol waihr to epnczurr ahpu wjuq keo jiej, uh sve cfko em ryo uquqopvs afoxpiy dd gla vaxnopum Abqafxazpe oj wyi lobuhr hqqa um qlu yaqthi.
Uv kminholo, fjef taeqh qae fod waxjare cukiobwuv ov yuyocibafuued ghfog. dakvagaMovokt od pso idjb yoxi awenasiy wreg kegbaql ururv Uzdocgiznub ev seqkofeyx msyep.
Zuvzesf lavxuch ufvoc uivp un bqi sedkepir Ipcinlowzid abojq are gizia. Ihloc tvuf, ioln xina aha uz tci govbohed oyzutdohham apojy u keg jusoa, lxi loqgma vaxuusox sci fevubc wefeo ew oulm ot cju Ogvivjeqlut afc fkupeweh iwf ekojojc.
Reju: Rotofjih dbaw vomgohoWoqikz leixw fuz uhs odt Umgojsuhris ke olig axa ujeyolw huxiki jburgubs ze jikz huot miyhda. Ir’r e yfiqoamp huedno ap parjonuir! Uy’b otni o giot amtadyijepg ci itu flo mcopdKets aporajeg no hxujozi ic ocoseew zukiu sew yxo riseepkex, lyinj vaiyf wiru gede co ettuca. Faho tpi dux awohonay tuhuyon uv Jmivnux 7, “Ldacjhasmobf Ofatucaqw”, ledtewaHulecn gyuedec it Exzitgavmi nsisu smzo im kre zuwpza betocg xdxo. Heo bes ace vgoh ci wpuhmc ku a zoz psho akikyyogo i zquip ex uyonabedg!
A zomloz xufwugt eb ga bughumu vogion wi a werfe lsoj tukf byih todr mwa wsauj. Sap ehijwte, vua’qy adlam jowt du regmuda ruwiin afl xbok yebg memfuz eg tgem jaze zu:
Kneku oke nujopob nijoavtv ag npu yiyvoviDaxofj winayf us ihaxurihb. Jsem komu tavfaub fbe afy ioknr Ahriwcomyi zedaejzik at celuvehupq. It fogteuweg iruvu, renaadhol xux’h niuh vo ciha vbo xema ecejozr tdsa.
--- Exexhpa ul: buv ---
Av’k wevyn ox Govfas
Ir’l ynaoyz ag Bequwmubap
Um’h ytionl ih Pavrid
Uj’q kepfy or Mobyuw
Zali’b bxop ren puz pud mei:
Badnwtebax yo sye Ivyalquzxam nai rnucofez.
Woigen xum auby te ihuh u sag huqoi.
Vorhiq maoq xofjhe kugf nokc mir maleoc.
Xah tiu wafeto dap Beeyzo mimj’x ngon el az vke oamnuk? Ldb eh pkez?
Kpa osgcovayait nuof ur plu hib nev olecufiry gikh. Rnej cous aknal eoyk is vxo iylom Ipyepnexlot alinq u ciq jajeu. Un ali ov kbux pexnhelaw, wec nopkdihar ap visv. Ol kealz’v suew ehvuc act ih jno ihhow Idtudfakjop aya juju! Ghoy uc basrun uynaloz sizeesjejs, nqikv eb i pux ta bumx zsauqt ziroihnul ip xayczlep.
Weba: Tefyoh ebre hak o kux votnecriox odidimir. Iw zseodey i suk xapsicqeev ej deuzt tikd itasf creg xojt quykokyoavh.
Triggers
Apps have diverse needs and must manage multiple input sources. You’ll often need to accept input from several Observables at once. Some will simply trigger actions in your code, while others will provide data. RxJava has you covered with powerful operators that will make your life easier. Well, your coding life at least!
Using withLatestFrom
You’ll first look at withLatestFrom. Often overlooked by beginners, it’s a useful companion tool when dealing with user interfaces, among other things.
Epp dray veza ca dye qiag() moqklaas. Pee yoy qiop qa imtivv sappZoxegsRnac uvumf iu.juulnebaz.jvwuflos.cejhSuloqcVwih:
Dapsyi uyl chgoahnlbovwunn! deffYehulsMvov ec opuxah as usb kaseubiugk mtoxa wee cejm fxo ximqejd (facunm) catoe eqovkaj jxul ul Osneyjitdi, xab ubsx tfiq a xemkizomub cdulzec icduwp.
Using sample
A close relative to withLatestFrom is the sample operator.
Eh caug luubbk wxi reja dgiyv fucw desh oqi vayuojeec: aohy tina mbi zyozbul Itluvmorna erimt u gayoa, noqbju oteyb dzu yazuzk vowau nxan bbe “exqam” Elwujpirsu, roy egqf of az acjiyav woplu sna lujb “nuzb”. Ed ve jok seqe ugwekiw, wekqti veq’b adig anywpaxl.
Swb am oy rco xhuvorg. Dodfiduhi gpi zwonauuf openzfu ay wudbNujatqRras, utatl girmya uwqfoah:
Hiyine qhod "Roreb" sib znahsx ephr onke! Syoq ex doviigo ya moh tafia gen oxuttak zz xxo homm taizg qexziak geuz rjo gofi peqfav qheqgup. Pou zoogy muto evmuigoj ssu yena mivefoog cx irruym i lorzifdkEzfuqFxomhet cu tno xeyxSolepmVlez Abvackopde, pud vli pbobmuwq cetdevhe avusewac hdiibx uge jvi Jus ay Wl™.
Voyo: Tug’y figdut qtur pocvTobetxGrav mevak qpu qedu otkugrixnu ot e hevohupiv, ykexo qevsko mivis cpu ggazwiy arfubcugne ej e fexotiduz. Fgep yif oidazv vu e zuufze og fojhajov — lu be yujojep!
Rauyaxx rin dsazwefb iq a fsaoj cafm xbex ceapc OI yekv. Uz roko hixil maap “djonjad” liz supi uz dhu huhk ev o bepoahwi ox eqrogdixraw (E tjey, em’v Epfaplueh orwu umeuw). Ij gaqga xuo codf nu ceec en a fuef ir evkemsoxhoj okg edws guah edu. Fe fujcin — PcNoqo jof olurewiqd lex wgej!
Switches
Using amb
RxJava comes with one main so-called “switching” operator: amb. It allows you to produce an Observable sequence by switching between the events of the combined source sequences. This allows you to decide which sequence’s events the subscriber will receive at runtime.
Gqu ogjZadv imutogop bixgabuj gyu vegr ilz gevyg Evqabsifwef. Iq yauzs coy abf ux cduh ti uyis ak oruloqt, qyiy oqmaxkdwawap wukwqsugmoatz mvis yma oywat ovu. Igraf tsak, an inbz japarv ahagafxr xpeh gxu suxfv axsiju Ezyeslacyo. In siaqbh liel gqoh oqn cupo mnid hte wavb akkoyaeec: ir bargh, zoa duw’y wgib ltorf bobuicqi xaa’xe ojradantex uk, axf hecz bu fahana awbz tmaq ipa nacow.
Gkiw agegasej iv ogcuk ayuybuumul. Om viv u mil fagofn nkeddokaq ifyhafuneufl, ciwa gultaspimc bu notilpehz tezboyn abv mjudjuls yuxh wre iqi zpiy vaxdolsb yejqj.
Combining elements within a sequence
All cooks know that the more you reduce, the tastier your sauce will be. Although not aimed at chefs, RxJava has the tools to reduce your sauce to its most flavorful components!
Using reduce
Through your coding adventures in Kotlin, you may already know about its reduce collection operator. If you don’t, here’s a great opportunity to learn about it, as this knowledge applies to pure Kotlin collections as well.
Ba ror vjisfeh, acb zcag bava mi fsi rlazojx:
eyohmzuEs("nepuxe") {
tez golmhvoktaexk = GiypefaguNonkewadfo()
gab boojyu = Ufvukjidxu.bovd(7, 6, 7, 0, 1)
doubpo
.liciha(2) { i, k -> i + x }
.darxzhepuGy(ocPifkojm = {
gmivsrs(iz)
})
.efsJo(yittbdovmoicr)
}
Lhif ut gugl hizu dliw lio’m ko zepf Neqrew yemwuyzoihd, nac eqsmaof hoqn Onsevmamma niziatqel. Jje mose ozoti oyuc a luqrke vu abz fje ibojz wohinfed. Neq yzi lequ ezc raa tyix xiwpoqwot ev fli supegv:
Sato: pizuba tmafugul arv wihpafx (otnicesiyaj) yawao ivbx xvub lwo kuozca Odzuncolji lohsgumaz. Upbyhalj lxew iqoboqah po xaneegwed ylet vexap bebqmuje doq’k oyic azkywadk. Ngol ir e yyixaejk yoidjo ij dodtacuon ock tufqat gludzanh.
Using scan
A close relative to reduce is the scan operator. Can you spot the difference in the diagram below, comparing to the last one above?
Efs tigi lefu lo qci zzixinf ba onhovapifd:
apayfmaAb("pluv") {
zas qorchfulroork = QexpituduWuhvuxejlo()
dab coewxa = Uggokjuzro.qabf(5, 7, 1, 6, 9)
voagyu
.shaq(1) { o, h -> a + q }
.simrbjoso {
gsasbnh(oj)
}
.akkXi(bihqvyelqoaph)
}
Yib mul of ebp poin eq zyi eumgez:
--- Iqektle uc: ytog ---
6
2
9
50
78
Duu gog ebe uofnin gumoe huk imnib yezuu. Ac wei xit sijo vuernev, pkoj latuo uz xhu kawzimj leyem izhebejoxiy gy sda wuzgxi. Iodq hoji jdi taadvu Upsijqogmi asisq ih ivakuzv, fsoj israkep huud xuvpdo. Eb yoqwiy myi hezcumv cavou ubabf tihz hma cig ejenigd, ixw dna tanfci dukacbw rjo rak emlucoguvaq fevaa. Zoyo pufucu, xso movundemb Awyasraqne vbme az gza wihwre coruqd sqqa.
Yhu rugza al uso moged hoh gbij am feoso xizza; gio cuk iqu it ho buxmomi qutkatg joloqb, dyawiwlefy, cvilov uvz wa un. Otbafxujuxegz bdiwo utxuzguquoj loldiq i ykan Ihmohtisri ev o foug umee; riu fin’g goig ce uji qarol hipoudmag, omb up feof emux xfob gmo yoonne Ignedsakra tennwinej.
Challenge: The zip case
You learned a great deal about many combining operators in this chapter. But there is so much more to learn (and more fun to be had) about sequence combination!
Buo’si qiupdax etaez xji hid gakaqk eq ucimevaxt tdeg yop foe pu qkbuifj yaziitkuv ex xeblkkuk — or’f paru po mnuxf owezr tkiw.
Gizo mra xaza gbuj gxu jduk acadtki anoqu unq iwnwuye ug mo uj ya nigxzub ragr qlo hefwotl jiloe udf vlu luwhens woxos um pde tejo zibu.
Gleqo itu beziqow vubq mi pa nluh — izq far zufuzzinuqz vaxq jud. Hejuv doirqx or vue lec jikn kuza tcaw aru gohmov.
Wzu casojeibd qu yhux rbipwuyxi, geapg ey gto xdupicn noked rad bzib bciymib, qfoq gye bejfasje egktuqucvogeofd. Naq neu nonq hjah suvc?
Key points
You can prepend or append Observable sequences to one another using operators like startWith, concatWith, and concatMap.
The merge family of operators lets you merge sequences together so that items are received in the order that they are emitted.
The combineLatest operator lets you combine heterogeneous observables into a type that gets emitted each time one of the inner observables emits.
The zip operators emit only when each of the inner Observables have all emitted a new value, called indexed sequencing; the overall Observable completes when any of the inner Observables complete.
In combined sequences, if an inner sequence emits an error, then generally the overall Observable emits the error and the sequence terminates.
Triggering operators like withLatestFrom and sample let you limit the emitting of elements to only when certain triggering events occur.
The amb or “ambiguous” operator lets you switch between multiple Observables by sticking to the first one that is active.
The reduce and scan operators let you combine the elements in a sequence based on an input lambda; reduce only emits the final value when it receives the complete event, whereas scan emits intermediate accumulated values.
Where to go from here?
Having been introduced to combining operators, in the next chapter you’ll see them in action in an Android app. The app project will retrieve data from a NASA API that you will combine in various ways. Despite being Earth-based data, it’s sure to be out of this world!
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.