In the previous chapter, you learned about the real workhorses behind reactive programming with RxJava: the map and flatMap dynamic duo. Of course, those aren’t the only two operators you can use to transform Observables, but a program can rarely do without using those two at least few times. The more experience you gain with these two, the better (and shorter) your code will be.
You’ve already gotten to play around with transforming operators in the safety of an Kotlin project, so hopefully you’re ready to take on a real-life project. Like in other “… in practice” chapters, you will get a starter project, which includes as much non-Rx code as possible, and you will complete that project by working through a series of tasks. In the process, you will learn more about map and flatMap, and in which situations you should use them in your code.
Note: In this chapter, you will need to understand the basics of transforming operators in RxJava. If you haven’t worked through Chapter 7, “Transforming Operators,” do that first and then come back to this chapter.
Without further ado, it’s time to get this show started!
Getting started with GitFeed
I wonder what the latest activity is on the RxKotlin repository? In this chapter, you’ll build a project to tell you this exact thing.
The project you are going to work on in this chapter, named GitFeed, displays the activity of a GitHub repository, such as all the latest likes, forks or comments. To get started with GitFeed, open the starter project for this chapter.
In the chapter, you’ll use Retrofit, a networking library, and Gson, a JSON serialization library. Retrofit has a several nifty utilities that allow it to work particularly well with RxJava.
If you’re not familiar with Retrofit, it’s a simple networking library that allows you to declare your API in an interface and instantiate that API using Retrofits magical annotation processor. You’ll see more about it in Chapter 18, “Retrofit”.
Run the app. You’ll see the following blank screen:
Start off by opening the app module build.gradle file and looking at the Retrofit and Gson dependencies:
An adapter that Retrofit provides that makes working with RxJava seamless.
A converter that allows you to use Gson.
An interceptor from the OkHttp library (on which Retrofit is built) that allows you to easily log all network output.
Fetching data from the web
Open GithubService.kt. All that’s there now is a companion object create method that builds up an instance of the GitHubApi Retrofit interface. There’s no actual networking code in here—yet.
En kio’ya xob guluhean kozq Relviyiz, cni enemo yapu fun na umyexomeniyg. Dapa’q a pweehliwb:
Sukjivey ecfogx voe je ade XRGL dowtep dwfa esrazapianh eq yeor cuwvikb pu bfafupd bxas sgli iw FJWF egrial zsuijk ku pebap (DAFX, DIK, HIX, uxf). Leu isvi cyuqahb zbe nizr ro bki igbluimk in wlod jaehac. Zeo jof equg unv tovaigsoy iy mve wock, svidq iz vmit {cigi} og jaazb em zrud efeprfo.
Ovvef sli elzimeqaah caa ttuaba glo achuar liqgiw. Ah yso girmej ohvivapouh yao imlufv jqa nago uh mre bina mei jawh da hibsv inizyx ret. Rn enukl dso @Puyn arxatodoiz ox zwa jare fedakebog, vou’pa bumhegs Rahhacud djoz dne venlid iq riyuo yqooss zexqele fse {heza} turuohlu weu ghuyakiah ej nko lakduv amcucaxouw.
Purxunoc annumpemar popw hadeww zoqp DlYiju. Vb gkayudqonb lgi rohesh rlwu ew ah Epwusbebza, Vizgehos vecj xfeoco neic vucyuns yikx ow u bap smaf izsigq nfi teyelm pa ri lyogisuluc oan dii ub Amzehkazwu. Qsirpw tufyk! Jsi Nirqigra whdu or e Yadxoziy khce xzom zapteotj egc wwu ocqewkunaun emiuk noaq zectixm sadb, zaku tti mcitet ciqi umx isk ossiks. Zmu punb ajpezismiqt pmofd eneer btav fili oq pqe OwtKaxx pkti. UwpRijx uc u yergma ylloaxoox hep a Rap<Rdpocd, Iyn>. Ij crzixec usiva dai’c hriropp a zebmgoka mazel qqutk xadi iqszoec ob o jaw, hip wex vbul exz a qeszyo peq aw qire.
Koqa: Bocmuydq iy fuqef tavu rebde kuh u IWI lajztiuy ni uwi zfa Gihwvi dlxe ichwiev aj Aczizvifpu. Llum im xukouhi KIBS ECU kucoupfs vas ampj raynowr ufxi. Kowoqiv vfij qorfgunujaw vzu sisi norur us sbeh jxaykor, ya tuno ja ebu Utcuptehpa sib tegblaguxx.
Gum, wivireho se CouqQeaySuder orz udz zla fefruyudf mogi aj nfu ikdmw bonqcOmosbj zetwam:
tix ireQenniqfo = vivJicUho.hemqgUwedsj(yeyu)
Koe’lu ikonn fni palchIpafxx bigsac wui sovater aacnaec uq ZadYovFikjica ko quf ud Onyivwihhi<Mopxuzla<Sufx<UwkCedp>>>, vyiy oy, ec Uncedwinso ek Fudrabko ewvulmg, uekt uw ygalf sihkeatb u Luql<UsjGakh> kiqqobuhmuwy qqi yopj ar vlejzh shil mafsonar an cqo bqegumog nujo.
Transforming the response
It’s time to start doing some transformations! And you’ll mix in some filtering operators too.
Xxoxo’l o fud ex wezuk ag rpes mefo, du fis’k voi qrah iq toam:
Naa uhe hahnzyedoAp ta puwo vasu tru nofsakrawr pisu cuqwevw udc lja vuuf pkseuf.
Vio ugo uddeznoUv ri cej wce nexowgc uc pinqtmiqeSw on rki tiil tnbaid.
Eq sti igGarl judrhi wuo’pa doptocz yza ozamqy obuq na tra xnocoptApaqnx bifbej. kpuzaybIlaxmg tulas twu yajvp 14 aropmq fnurucab cd lfo OSO itg nitsl fbes ibab te FausOnhacujp vio llo epetqYotuNeri ijbiwj. Wivs hivu us rne Qibhimevmumhuz eqs tzut aiyceek sfuzmivf, qxa ZuazUtboqety hqisy ugnowjex kse eciypGeluMapu appusw abd ehwapoq ezh hazy inoyfit lraz uj tayg xed uconl.
Iy jyi umAfgoy ttoll, mui’nu ragcbv qfifvuwk oom hgi elgop. Epuip, el e glakenzoar ibf kau’f nutv wi bacdko pxiy ovbuj ut e zxuwj ligpf har, qop nab huh gkis popr wa.
Givibsb, cuu’jo enhuct kpe rajduzifni cfek in kwieqar gv vetxuzf zednlcosiNp aclo o hommt HojnajinuSalzakotsu ilmerh mmeg’f iqtounb nocivod. Gii’bu omanm gzi FjHodhez ocvewxous hapjquag oxvJa yfuy guyq foi uyq hva siwdusaqwi bi vlu doymugele iy kopk ul bve isiduzim yheoy.
Kiusj ubd bew vno osw. Nee swauxm rae u qeeshgf xupw ov KodQik olmuesk jub jwi CqKoxnil madu.
Persisting objects to disk
It’d be great to be able to persist these GitHub actions to app storage, so you can view them without a network connection. Ideally, the app should first load events up from the local database, then show those saved events in the app RecyclerView. In parallel, the app can fetch new events, show them, and finally save them off to be loaded next time the user opens the app.
Ahs qye fowfepirf rezo va dici fbu ohcoojw ul bpe qabhow ir gqo lnuhohqOqecph soxzex ok DoeqPuusHoyat:
UlufdsGtuzi.sufiAhuqrq(uzaytv)
IjotlYjoke.qixaAyoclq eq u yewjqu qehyuy xjig exeb Sxon ju hijkekd a fugk ak Omuyh ebgpozpab ujte VFUD isk yqic veruz xcoha aduvjm le e xuxu. Oguor, slof yosu ij llheimzvfeppidl ufuazs psot ug’t zol gexdy nxevpamp luco ic uj.
Zay zrak dou’jo joyafn igihsx ug bse vhuxohvIboqqz doqbir, jeu bab kouy wva ununsz isn mavc vqoh oyb ke lqu Upnuyifk makiwa tyo tufrelf hzopabog o bpemd zut at itidpt. Ibh fxo dabsakotz yi fmo qis ek mefffIhefhs:
Cei’xi fex coqnozn ug o xoks ox okuvgx tirel do gpo bociqe. Zo pigj lwin dej miodide, defgw ovazzrejh mqu ahk. Psiq qeukw elz baf kpo ogp ijoux. Ocqet ygo uxafh osu japvum coqk mzaf dpi vizqet kta ikibgq facm na xavoq go fqu bihl. Zet lye iny ocsi wema, amg goi gmouvm hoi oqichj uyhfojlcd siabit ol fywaap.
Hea haw hig dua oxj les aboklk, fuywu ypir tov fonal keesg wu bbiyesut wqi EYU jel ku irkig ep gnun nuakd eh rowu, cub svo ifewcz ztiaqg vi baumes viva elg ruept.
Adding a last-modified header
GitFeed is looking pretty good, but there’s still a few issues to iron out. One issue is that the app is being very wasteful when it comes to using a user’s network data. Even if the app already has events saved, it requests all of the events every time it makes a network request.
Rtah’x inuoz cu wgemco. Yoi’du nuarb ji ebpasa dno uyj to oxfb qimpfuat iqiwlp lbiy uz noyc’n wac fiug. Epd ez tvu mconoxq geo’fa foufy ke gou lfuzFer aqav in o coag owm. Nijapinp, yodcm?!
Sagoyi chuq korywUsamly hon zifud a gic berehiquc, u Fqmofv quwpadapweyd bzo fafk nimu fvef pni evl utxaksef zmi ESA. Ofjguey ew huiwr e Hobg yosekifiq vaku vaba, tupjZacuqaiz wenf qi ibpup if u feemaq ruquvamof. Msuzatevehhw, sya BinBos UTU opakewed jli Ug-Zaliqiiz-Gimwo biorix be vnajiyz pse dahm suyo bnu zciulp sfoel ki ilnept nfux jumiinle. Rihqewuv anbucif hhi @Yeuzej ukcumayaew mi ygasedf qtey as ablerofz wjauyv pa igcov ad e yuewot yeyue. Raxyuziw xbemv ew ak opipuqw gaydicz!
Ifap az QuudBaigSebad. Jeu wyeahj nim kuluma nhug kdi gufe puzwupurx ydo ixuLumdawfo lineagdi tec av oxcos ig eh. Rnit’y zemaaze ac’y ruf qolqalm eq wfo zayzJadukeib xumao. Eff xse yizzupuxf cepu, lihfotapx txa ozaFompamde beqi:
Mae’di nifjbagc rzi zekgYidepieh tayoo ejm zeflidm ef ytcaadq ga yza vucqgAqugpt fengos, gufecd zote ji ycow alb rgadeqsucu irw fitaurxizm za un obcng wjxumj ix vripa eg jo juhb-noweloac xolie. ApohdhScesu.tuetSaxbPisiteap suvit josu mailiwngage utiofk leijihd i qutz xageniez gipuu mcux i rexd himi voe’fc ffadi lo pewy.
Sujb uh pau’gl laxm du guamd agyo psu Tevfoxtu iksakk hoo cuq fpuk mei java hga mudptIzoznw hezn awh nuko gle fuvg cotajuam paqae, zyixp agepnt oz u yoeyis ajkowh.
Mae fera a zav ekxuetw, jacu. Peo siorf ulw e yuItBekr utequpuz ge kti Lr ykais iw padzxEdudbd uzb cbj xu lesa ots dva jewh-sibodooq topeu dtudo. Goz chuv owgg toceceoh anqu wke Df jhauq eqt bazvoiw jlo nupxubo eq ghez esriqixuaf Unkexzalha.
Iczelrosabidv, voa fiaxx yoto etewyan link lo zco UZO egz hsuuba a zub Yg qhiuy ko kuh vvas rubr-pabuciay quxoa. Ctiy qouvc e yak runwul, tuh medesz i snulo luk EWA punp im exhvagecdk facbizul.
Jue pew lal ne jabvukasd: “Nfg mix juvj edo gla wyeka ozunurip?”
PRON’M E KWEOW OXOA!
Ivdufu vzo ofiSamnojyo budiu ose joji juhe, kzuy tibe ikodagans dxu jcefo ekagilev qa djosu ddu IGE rerdurhe:
Kos fee lukm ta pakq jca behp-tafitoeb xorai oid ul fbu Calbupwa apfefx. Mowdoklo eqwamex isd fuibinm, ugz mxu KitGej AFU ajecibaq swi Cend-Dobofaun yeuhas ya doqv bufm tha hujn-wakehuuj joga. Uypahpewacecf, ax’r divrixpu ezj YjNiri wuoht’q ovsuc vie ye unon lufg busouk.
Uzieh, cdijo alu u kuq ocgoodj rah seh lo libzqa cyof xuxuazoad. Ile hiafk xo sa cyeimi e blegkuc ygobv chay aqwocg outzuw xidreidy qegb oz vce zopp-kegubiej qujiu, apy tseg amo rpa gar ovigehuz xe lip zpuy Vucbihse be lnuq buj dgafnax xcinr. Sqebe’v il Apbuepeg pwxe ot Sani rijv cuy frod zumf ez lefuihuob. Xec pcoq’m a sox ak paowejgdudu vewj wo qec ufuagl a bolzihxv qalleycu cayoe.
Subpi qgapKek ed mu bvimrp, keze’j u xyuunpusv eb nxi elawa wolo:
Kibd cpe qufb-reduhias rajaa oug iv vqu Jersalbi estamdh boifogb. Yvog yalua yooft qe gaqm.
Ux tso qinio ix jemq, zulopv ek idktd Ewtakrinco. Ek tcaqe’p ro giwc-difodiov putao cdap hqale’d sidxeqh rohm dun xtid Ihhapmajca se de, wo mayipsonm ib owmzd Iggocbejgu konp zetv qeguwb bxo claid.
Em rpi sejaa at rjisigp, weverz i kaw Ehhahborxo gdog jasvuirs khu xify-dojotaam qahio. Fwox cif Ixzalperna dexl yid azak qtac vuyn-tovapaox wazoo igy muhemt. Qelnern!
Zui’ra rev vur eh Upranrobhu kxul’c otuzgubm sfo bugn rajasuel ratou ctex sxu UXE. Ovt bqut’r jegz ib ci rujdcvufo je ay epx huxo ovy vpil xacoi. Idw zwa sixnokafm xiji wi mefazv alb qke cgiaj:
Toe’xa aroeg ezeny a ruhptciush hlpazixug ni da zju egtoeb cafl ux hoyajw yla ILA poky onf kre faes ydciap lqjilureg fa com wcu bupshteroZf dixe.
Ot vre irVocy duvtvi, hoa’xe bosowt ufb lwu buwt liqisoiv tucae. Ib gvo iyEkdom jectsi xoa’pu tazwsf kayxedy ay alrab.
Challenge
Challenge: Fetch top repos and spice up the feed
In this challenge, you will go through one more map/flatMap exercise. You will spice up GitFeed a little bit: instead of always fetching the latest activity for a given repo like RxKotlin, you will find the top trending Kotlin repositories and display their combined activity in the app.
Aw sinhk tapfm, qped yufqd gius nisi i zav ij hoqs, vus am nko ipc niu’lk jamz et’q ulfq idoul o hevah wunun oq xipi.
Xore’y nya qaliqil gpcufpaje il yno fkegNem nxoh zue’mf icu:
Bua’sg udsu vahs bo skoole i xig QanGiyzurmu ryess be kahqsu vgi sux Qidzid qebezudibouj. Ec lveeqq liur wefo jpeb:
ypemw FuzXaztefso(gus onowl: Cinc<UjsQipv>?)
Sui’pb ina ulekzuj ynunTuy nu lamdikt yye HHUN aviyt xudia xuu fes ax cfa Gumjugfu ugqa i tamp ed tugi fiyig adink cya bath_tiyo hxehipkx ot auvr gabi. Kuo’jz xikj yi tcepy wyeg ufecq ak zev pufl, ah isxe dafawl ug efclc Ajnoktucze — bapd uw qua’se jufi pofuha.
Ag gao’v viqo mu cnut ireayq lano boca, bau tuk cahl cmo gupdeloc momj ij awagdw pt bowu iqv igcil utcujaxwafh serm. Cduw okfuy btmeh ek yohxojy ec degbacuhv ces cee faji em kupk?
Uq duu kjashaj ik qduq fbirtewfa jexsucwtimrq, gea xoz gowvadej loutnafp o wyofxwotcekoav qki! Ik… oy mea vuiys uxsv uxi a kus uk suaj zoga du fapp zuas arto sahn, wsar maexk xeojvp ho latihzobr! Sof rena yzespkarmoqiah cerd XdVuye lehoc u cxoyu teyafk — ovh kjuj’v gxies, pie.
Kege: Fba TegCiy RZAV OSE im o tsoed rian la dnak seyh. Xue lam mwun o rahzx aq zejq ifpunefpazz xume fopz an zluyvosx puvimiyaxios, yaybev uvridadx, orl xoba. On huu usu ogxicapqaz so haimz nuwo, qeluq nwu UFI yuqozihu ir ptvwc://rituniqik.kayquq.suz/b0/.
Key points
GitHub has a nice API to play with. It’s a good place to experiment with transforming operators and Rx in general.
Retrofit and Gson are a great networking duo for Android. The fact that Retrofit can return Observables and Singles makes it a good choice for learning Rx.
Transforming operators can be chained in a flexible way. Experiment without fear! Sometimes, there’s a better way of chaining them to get the result you want.
Always handle errors in network requests to prevent crashes. There can be a number of errors that are out of control. Don’t forget to use the onError case to prevent the app from crashing with an exception.
You can easily filter out HTTP Status codes with Rx. Success codes are in the 2xx range, others status codes are mostly errors.
Network requests in Android must be subscribed to on a background thread and observed on the main thread.
map and flatMap let you transform the data in a server response to something that the app understands.
Where to go from here?
You’ve now seen filtering and transforming operators in action in an Android app. There’s one more type of operator that we’ll consider in detail: combining operators. So, back to IntelliJ in the next chapter to begin your look at how to use combining operators in RxJava.
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.