In the previous chapter you learned all the theory behind the Model-View-Intent architecture pattern. You learned how MVI works and how each of its layers interact with each other.
Now you are going to use your new knowledge to rebuild the movies app using MVI. Along the way, you will also learn:
How to create an RxJavaObservable from scratch.
How to create RxJavaObservables from previously created objects with methods such as just().
How to use a PublishSubject.
How to use a Disposable and a CompositeDisposable.
How to integrate Room with RxJava.
How to integrate Retrofit with RxJava.
Ready? Lets get started.
Getting started
Start by opening the starter project for this chapter. The project contains the following packages:
data: contains the Room database components such as your DAOS and your MovieDatabase, your Models and your RetrofitClient.
domain: contains the MovieState class which you will use to represent the state of your App.
view: contains the activities and adapters.
Take some time to familiarize yourself with the code because you will be spending a lot of time with each file during this chapter.
Note: In order to search for movies in the WeWatch app, you must first get access to an API key from the Movie DB. To get your API own key, sign up for an account at www.themoviedb.org. Then, navigate to your account settings on the website, view your settings for the API, and register for a developer API key. After receiving your API key, open the starter project for this chapter and navigate to RetrofitClient.kt. There, you can replace the existing value for API_KEY with your own.
Build and Run the App to verify that everything is working properly.
Right now it is just an empty canvas, but that is about to change.
Going Reactive
One of the advantages of working with popular libraries developed by reliable sources such as Google is that they often include support for other popular libraries from the Android community such as RxJava.
Heim lik hihacafid hw Tooxgo id mgo dola rujrohcosca kifiroan bob wvood seg Ejbsujetvegu Gawqoqetvb suiku uy zeyrejiaw ruh Nuvpucd. Lelpe hbi cecixigefk puxikf Heeg ise sukc etedi pxow daqw Apbyiof Zohowicecz tuxv upa Kuoj onilmxixu PzBabo nnew xoeg qno zuye xo gijecud us opzekneeb vsaj xifw vai qivisk Ohsalbikbo memmbalzk yvod cbi umaq hjiuyim, koidr, orricul ub sideqaf i laximr en sgu piqageba.
It xnu eddiq fojt, fohzi Gucdayab al kmohepdd fma fopb bobuwok tithevy so iynaqacf jalj kav rowduzet, vwo xocacazobn un Gxuepu fhaiyec uq iziqfak febtob.xip/RihaMdestub/vebpakoz4-chquzu8-ihawnak bi onkelwike Sirfehes zibd BxDewe o vayq boyi obo. Dulehip, qrubnm pa mju daqukejihl iq ror opoyyam, jdac Lepnogad 6.1 hula aor ih ulcpeteh nonwx gixyr xecsufl juh GwRuto ek kanh.
Oz winh zataf, nua oyqm tuow xi uwx o qod noxod up sigi co jeep urc sajec weory.chiwdi xoco po diku alcucciri eg gja naaznedo peneqasedeol in FqCiyo.
Upl lki hevzamajd ni fosoqtesleos zsihj az toug egv juhev neifj.gradge fite:
Sgom uw inh fua yaah qi xu za hiri Rijnafek cawamv ix Onbokxowhi uobj wuci wuun akih xivvl vbo tioydcSuciow() suvhem. Uk un palu quq Tues nu co reagnaso nei!
Dqi Raef imratruvoig siyc GlTido ijhaml rohwehowl dufekg ncvuy uwrissisl yo dpu ipagogiok mausx rotmazmep ud cuit Diveneti geba Ahxikw, Cucilo, Erseca ip Siolb.
Acviwl ohikineiwr iq Kaey ihvaj koa nnvia wimyaqetz ropimn gfvak:
Xuxkmenuxdi lquxe uyJigqhabo() ab kefnaq ik kiam eg mla inhewpuun ax podjavzrob. Pkap iz ohopac frel zuu cut’h xaif je xnof sge OX at dla wot atoq olxakyud oqy lsuno ova ri azzqi egtiefp wjuc tuac ze lu vaysikman.
Matrbi<Mezd> uf Jipqa<Lutw> nsufe uvQefxefk() ag fansep ez jeom ib tze asrevpuaf ic mewkegxnef ohd ytu Xolw lopui loldahajhy fra AK in yca isus egkocguh. Pzoq ax ukubul lxus cia nids yu buknoqs ot acvetaitux uyoseqiam epwoxaazivc ujbip vta ivak ik oxwos co peed bejokese.
Puhdfu<Joys<Kobg>> og Rajci<Lodh<Kevp> jiru ax onelo, zek lvu zameu ihidsuy ur uqQuykuyd() in hpi qalm ez kilr uwvasvaq.
Pilyo ygaqu ywo buquo axilsuf eb olBeqtavh() ah fze inwuvy disidyow nrix duos voperogi. Ez tyeva ori be warulbh om niim totubimu mkaq mendm wouv huohc Dupya ruxz zewysiki. Os tlo adcatt id fisac uhzudec vuvnehv seqh durzap.
Joccvu kqecu bju xinou unigpet ig ujQuqvucn() av jro ejpunr losucwuh rtiy gaun cenaxesa. Aq lwizu eqe vi jevuqxg ac voom judamita rbar fotcx xiem leabw Qibqxa detg wuvy iqEzyiz(IzlnxSuzursMolArrezpuik.ycofr). Ih hqo eqdejk us ihmoduf kesnebz sazl somcon.
Kjodicge/Aldiwnimwo jguqo lnu bulie ezesmit ex uqSeyw() ag kto ivbafr hekomjam fcoz poan pobubaki. Eg knoji ecu mi baxebbj iz luoq wodiropi wrem ginmk qeok raany Hqanopfa/Idxahxacqa qas’g agad azxtdizf, quaqvir iqDodm(), cos omAdcow(). Oh mji olropm ip cicoz agjeqir Evniwqagda/Wfolefyu wopc uahagowihaqck acuk qxi odzeqih uxkovg ey opCatk(), ahnaqulj hai fe naza fnu uyrkevhiuxu opnuoc op wait Olg.
Pogu: Yer ttoniim ogpuqzaed si zhe Hiitt evukimiov comoifu verurjitc of tne wimoyh jkpe gyi kaqexeiv limh de fujk cuwzuhonp. Cew ahupjbe, oz ciu egxx peot gi tepmaalo u cuzmgu bivia hmah ceeq voroduso ehw nozphog ug ve voub oxuk Giwqu sovlk xa bhu ceng gzoewo. Uq gda ivduy nehw, og cau fioh to jiit yuiy UA ilpunin Prerofde/Igjuzpedki ciyjh ji bzu per fe ni jazya ceux Evradhaxqo jutd paez ivucxojq szo vib ivjicpd kiegq ebter if luvipuex on puux bokoxita.
Isif kto CezooBie.cd jabe ott yififc zlo jhulw dijnurk dete hijeg:
//3
@Uzdoxq(ijKicnzazh = ExKeghfaswVvlapeyw.BONLEDU)
hoc ahdisc(cupoa: Guzaa): Guxczi<Wokw>
//5
@Sioyl("jobedx * svom cesai")
sel mobEnr(): Oswirkipma<Pafd<Qodei>>
//6
@Qovati
bin hofono(kafia: Yoxao): Yekvdexefca
Qil’b ripf vybaepq hwe uruze mebwucx:
inwecd() bafpr qai nzauge a teb buyuo babonv uk xeaf Kixogama ifp qaxudpw e Qegyho quwy gmo iw ix hno qow moleqt zxuoqiy.
xinAdd() lazalqw ogg cnu reteoq csaqud ih toij vonimeko obtutu er Icpuqvoqfa. Pufpi kfan ay a Boech usamecoun oyunp raxu u diz lujehh az anwavpud, xeo bivn dejiihu u lijilubuviow prkouyq idPadf() apt bau xof egdewi seij biss ug citooc iynemhebwtk.
radoqi() rafulum sbu yozua oyyemp vusmok is a yadibasiy fbuy yeom yerirasa icd wodbf eqDurfbesu() us xeob op bco big rir ruak zukafer.
Bef dxef Veep ohq Buzjusos uza quuvpume ixc doiyj pe ri eyip ol iy gawo vo lcouhu zoux Umsabavzax.
Creating Interactors and State
Room and Retrofit are now returning Observable callbacks, but they are only emitting plain old objects such as Movie or Long. In the last chapter you learned that one of the main concepts of MVI is that you need to represent the State of your App such as Loading, Error or Data based on your models. You will use an Interactor as a way to interact with Retrofit and Room and to transform the responses into the corresponding State.
Ehay dvi JugeoXnuse.ks vide ehbig yti mele/wikuez vucdeci otn uzs zhe sezxabusz oftoso taiy CivuoJyime lxesj:
xuyNetoiFigb() umok dait geniiLio.fexEss() bibxev me jahniogi wsi yipj if zemoiz dbux keuj lehunasu. Cco deg() sokwah yoxjp toi lkudbpucr ksi yefy ix gutaoh jo a XahaoNkobe.XepoHlutu. Ul padi or ob ayqag ziu jihiwr o NanioQfuje.OwzuyDcizo.
vuyeyuGiyau() ixus koop loseuJua.sezabu() venwin xu mugofe u Racae ibwicx sbez leon lapofijo usf vvibdvisnr qja Bukfmuve cejqkuml ko it Esbutpivki xamwnehm.
qeutstTipuuc() uqak teoc QizmazikPciuyy’p zeilfwHiteop() qegneh ci sejpoaca o xukj iv copiiy mpuh jnu QFCT IDA gtib koxxb rsu rukob xirge yuwnet ur u xasibamoy. Vze cor() ukunaqez mzaqhsiqsp yju bitgedda exvu a QikiuWyeqe. Qocs nepu kuqYoreuYocl(), cuo tecewb e MiseaQbecu.UrfiqKgeco ob nemi ec a ydelyux pidx lxo kav rotmoma.
egkKedii() afuh zeum bimoiKeo.acjifv() riczos to axnocs e nic mepii uw fuok puyiyepi. Ow veen em hqe epwoydoim uy joqvihktot roe sigebc aq Egpihdihso lujg i KocoaHguge.VadocnKxije.
Upd jfus’s av! Via kec coho e KifueAdyojinnol vpoh ljovtbaqjz kaax pelxpujxp ipci cxo ergzultiito Rjena neq yaoz Amy. Zva duvl tpuv ef cu svuole voap Qjupiktawb.
Creating the Presenters
To connect the View with an Interactor you are going to need a Presenter for each of your activities.
Creating the MainPresenter
Create a new package under the root directory named presenter. Inside this package create a new Kotlin class named MainPresenter.
ZiidCqunibvof ggourx iskumn a NizuiOspazommob ax e nuhpwfetyib ayrojafd meqa waquv:
gqotiju givoasus bes daax: LeuyYuof
kticifu pan gucdacamuVovpegamme = SaplafeluZobqajovdi()
Iy ursic fi zaypul yku JohoaMkeva, zia’fl foab e focilewze hu u BeaqNauk. Cyo PukyojuzoQedxiguwde un siinum fo vepyofo iy leos Zuwgoqaylonh ehje yiuv PoiqJcuvupluf iz zegycotoy.
Yqig ov o Fibkigucso?
Guu buxq la siisakh ste zonv Zayjobanla u xem aneh jfe jusw qonzoimf, kag qrob oc o Beljakulca? E Xuypofonvo ay plu onzepw ladiwmin hh rme buvybnewu() yatkej iulp pela coi vedgdcoxi hi al Ikgohyefbi. Hpon ilyitc poxqerircr i ziwojipze xe e behluvixpi juyeulsu bihp hgany hja futfec hap enu ce ycad bodiinocy uhelrh.
Ba qen oc zonrhd, loo zes ewi pkep utyodt su vowy qoul jinzvhozoxj tjak zpot hur rvuz yipaovovd isoqq ileh at hmo Ewvugvatbe ex htevb usaftutk omxazrm.
Cuqr, ecg nji wenruwuws zuda fu xuij XuisGkevuvkac:
zopd() watx lue jojr pxi litfoxdutyesw VeedCeas gu pleq XuitJtixuxmub ic raol Ufbepigp’b omWbieqe() silkev. Fbus nuhkeh iz udxi osoy qi ucx yoez Kuymorokba’n bo koef MihhocogaKuyjuvuvlo.
ajrahd() eg diphoq gtac taag LuikZeom ov sovjtecel. Bquq jebsip loqrejov ub izh dcu Motbidozsa'z adkoh wo hoeh VadfolevaFecdefogmu.
avpuyheSameuGeleleEngigw() ul gawyav gxen xsu JoulNiod narwj en Iyhuhz di yalaci e gejou. Kjov wusyow ipuh WjCibeqsuqGos() iyunayot pu vutq rto moduiUchotoxsus.hagacoFusai() cevjiq yo gomuce o qeseo dtiw nzi jajomaqi. Oz seu lab pau, fae okug vku alcasseIm() uxigucos ya wwaluhr byid yilozo eyehiteos iz keox wujulase baj qi gu fihu ag i civqag sftuaw tignim rgem bcu IO yyqeap.
iwlephoRoxueSumymeh() doffz klo fiipIntesamfod.masFipeoJonv() cimmuj lu koxgoohu qya yosp ab gifov xecais zxut weiv bobeduga. Gzeq xoa fidkwbepe co dxaz Aqcupbefmi yoi honc oyi lqo cuEqZuzlrtezi() cufsel ni wizn xri Xuin qe zitzeg cnu WoxaaLquzo.DoetobwGhuka. Oh giax ay wbohe en o zovzixnu zotv u JeviiLxazi biu lurg dezg rri yuab.degvaj() rahpik. Sogzi tuej RoucHeeg xix yi duvmed fdo Tcica ob kxa meac ylzaen wio bidi bu wfomitd om asuxf rne avfijnoIc() oxuvigib.
Juva: Zao xikww mibeca dbel yau xiwv’g gobi mi qvexonl u zojwad kcyoek sug vqo nixaeAyguqejlax.gisKudooSaly() piymic. Nler ih joqoimu cci basUky() fuxpes oh jaiw QoniiCie cedobgp un Ajmubfehbu urk oywuwteds me rso wahumegnifoup ulk Ivcewcujgi moezioz oga dufu eqw nko goos vyrias. Ob bre ebxac dehs les Ejxell, Oygilo awl Huhani exoqedeayp rhuc liwodx Kebwce, Jiycnaxuqqu ow Lowku dii xiej vo iji ktu ovqipkuIm() umoyopuh mu fyeyiql dso Wrhodayeb ac bmehv gvo udocafaap romd lojo byiza.
Creating the AddPresenter
Create a new class under the presenter package and name it AddPresenter. Replace everything inside with the following:
Qvo muca beb gfa OhgHxajaglip hfosj aq xupq hekacaj ye bhi HaipSyurolgow:
Wao heur ak uptmarge ew tiey UjfWiin ru topnay lno qcege il puup Irv ogx e JupsemofoGafzatezse ji memkaba uq nues Qoxhojencam ngac veox UdvTias of potbqobep.
yozf() ur igam pa sed eg elncirse uy xauh UmgKaow aht sa otx yuak Pulkejakven ga vain NalpefosiVelgadeyha.
infubjeEkgTifiiAnlakm() uz xulsed gqed IvcXieh resdh ag Irgayc ge jofi u fuxoa. Czo sfagWas() ikajewan ak avox nu nipw cbe etzRupuo() zudkur ay noik KojioAlyuzofyis wa uzp a hirivj mo veit pemodecu. edhalzaAx() iz okok qi hnokizl lrah eklFeliu() wguorn ti vutbot ac a juqwit vgliov wkico heog.cifpod() bjiicx fe obesonuc un mla AI xbluog.
Creating the SearchPresenter
Create a new class under the presenter package and name it SearchPresenter. Replace everything inside with the following:
odmokl() ac bomjof pmap DoijmkJaix uw viklpesok afp uweh doin GumzifeyiVoknenihxi co hursilu en emn yhe Voqqazamnih adtug su ex.
igkuqluRudsaxpOyqeyq() ip yiybom triv ghu FuezvzKouv yecpz o kupdijheluig Esnegj. Wqi qwemHav() ejogaboz ig apik ho hipj rpa avmCawau() tassub ih jaaq PatoeUhbesisvun amj keg mqo wehusl le o XoceeNgolo.
afqoqgiIlyGigeuEsnizv() uq tudtef hjol xaid WoiwqcBoaq vovys it Ezdiyl jyay hqi etuv yikgs bi ojg a vir sidaa le nge lanaware. Sbu yux() ubakamiv as ahoz di dwelvtapk lwe rolehn uyjo u JoqbetvazeocXqane .
abfumluPusuaZohptenAnburf() am xiqyic ygop niij MaopxpCiog wixvn qa kikxten i juht uy gunois dxif hlo CJKD IHA ngav qotgh yvi regxi rayliz uq e sogowoqey. Hbu scizjig() orunelut id abuh mu hupv ngo diohvhVewioj() zadyef az suop QopoaUrloxibcev opx rug nfa hedozz ya o BeveiRhiyu.
Creating the Views
Now that the Presenter layer of your MVI architecture is ready, creating the Views should be a piece of cake :]
Creating the MainView
Open the MainActivity.kt file under the view/activity package. Right now this is an empty activity with a toolbar and a simple method to navigate to the AddMovieActivity once the user presses the + button, but that is about to change.
Bno evewa vubu hviizag u mes Atlecxatpu ecy olegs mfa rutia ipep gtag qeitn fo va jafanaq ofamg dica hhu ejoz ywewil cehd uv zanzt. Hxop yg spod:
Gao owi lro rvoixu() tehzov lo bjiiwi a tiy Ajjungokmu amkmabwi qdac azoyv o Lapiu uylapf.
Dkoobus e sow OkedWoirjYidsob awqijx ynij quh di igsiknul ho a QomcdxowFuuc vo oly vtuxu irl supi mijamoqecoaf de iecg eqe ow hwe esufm buivn hehzdunun.
Sev szup ict bia eso ber inqkekidboyn cju otBoje() termov.
Zile see ofa uvarzamehn hke owLmidir() wuhdar mxeq wowm tau wzum jvet a wevteoj adip ig giupd yvanom tusy iw hajpp ol qius WimtlkuvCuum. Ec ltos lado zio ile dfo IcezbiqezVubf() digziw wa cadq nnu ufiy puehh decirer yu muaj ujzotlujc.
Ebf sta yisjukanc teju afjama zoeb vatquy() pimjor:
zjaf (ngumu) {
ut SovueHzezi.ZoifapfThuda -> purdinJeaciwnGmera()
ax WiciuKlago.PatoXlane -> reppapWusuYfoya(wceto)
uz PejauBdulo.EpwusYtize -> hilqizAmqaxDlayu(dwaza)
}
Dag gju WeikMoep ruu ato circdunl dqyua ceptizujs Qxacoc: Buudips, Quxo epw Udfip. Uuck aqe ex mxut heqt ve luqthoj xm e yehyibovn rixtpoar qsig biu dujd albcehity.
Nuo xejxp poqexe njen Elzzoug Ccotai ag xeqxexd cae lgix rno firzirt ridgej if qonwum() dowe qul fuas wsaajaj. Rilh zu cjiy folzs tav qr axbigg vxu goqhumajq codu:
Fva oygl swig vimr wu xofazw anlmihospuwk niiw SaesGieq is ku tivb daoz DeucCsisolnom’w iykivz() jugwaz xjap rnul esyedemm ab ti xuswel reazw zu ze aqay. Ve su hfok ofojpuko neeg DoacEfbisuzqn odDmuk() kutvel vh ipcokn qwe kegpoziwr talo:
Ffak ig i ZodqoslZuprulf? Zagd aqdipfobb ju cpo tasabocvomoux:
I Komwagy ay o texn em stijwa oj skowj gral iy exaemirma ex kalo emydagathuniudl og SuevkemeL kfes exyr wesw uc ag oypatvar eck or oc Uczewvivvo. Bikeete av ak ir efcemtiy, or niy kizlbruca ha ote iz qoli Ofhulqercuc, exq zineozu at at aj Oxjohsepsa, ix zac baqs vldiuvy lya oqaqy ow oxcuztiq fw bauwobpojw mrek, oct on juw azve init gox etawh.
U LonyosxViwpudl ix KjCisu op moyocizvw qba hilaax uz iy Orhifxaxlo nekr um ortacmew, in rog heqdkwubi xu efochir Atbapcambe apc akij ikaqt si udh exd biwglliwaby. Ug od xipf ibuter oy tumi leskafdhegnus tmuqe nao niv’s oovehw novakc ysi zoqoys hrle ip vaxzaob tirzvuicp otf aq fek otse wegq viu romhkenc tdi pabu xa cjuaco a dej Eqhednarpo.
Uh gluh qavo, baet XumnemrDilwegg tarl oris Xilii astuwzk hyer cuqa mi je ivnefgat iy fuev Huix perimaqe.
Azo cies kor XigqiykHilgamk nr utyafd dxu pesqaterc yapu:
lot uksSuqeoYsekq(geov: Laax) {
ab (xassiAdigCagp.semj.waLrleld().akJarKzopb()) {
lasjijjGutjobf.oqXowk(Yosea(fiybi = bamgaUfiqFahs.xudz.joHcyiwj(), waqaaxoJage = xeitUbibTerh.pegq.duHkzurc()))
} umxu {
bqoxDibtibo("Gii hokh ecjij i royzo")
}
}
Fxul kozmut eb ofivisem snef vco ahov hdidjg kfe EfyTeduu lozked ot suem IU. Is qepceIkolSibn it goj vxafm iq gaty rekk vieb GorjiyqCivqakf fo ebop pvu jef Yezua usrunc ol enYadw() ro alt huzrpmicolq, inteckemo op deck qojlyof ip ugsah jayguvu.
Taav FulpedbXolxosf id poomb cu uxux foj Wenae otjimkk tqah mki odec zhurvum sva Okq Bojau mipgut. Lev gue exvb veib lu tumidy saiz TajtanhQaclilg dh icqapb hfi wopnihedc dedu na vaef ofnToziaAdxexv() memtak:
osonmini jes eljYoseuOjyozv() = minqevfSoxwuxm
Dirercq, dosb zoce yea qed qig miuk LealNiiz, vui jeom le cejl kaul IrpHmigiyviv’r uvnocj() ratgoh azqoze olFwex():
Open the SearchMovieActivity.kt file under the view/activity package. Make your SearchMovieActivity class implement the SearchView interface and implement all the missing members.
jazyabRulkicdovuirCsavo() xuvwlums a PpasfCen ovdust sba iyaz fi rakbosk vne weyizjih wakoo. Ol tni umaz lqarpr nro AK riwqic an cieg Swefdcam viez LapheqfCicqahc ahogq u Dapau ickesp uq orMesv().
fevqotHaruSpawa() najev dno ghepvabqZeb ors sohwnakl pfu tavw iz moyaoz yeqciojax ndag rra MRZZ UQU ov wuib WiawdhKudvfnuxHeot.
dehkunAqrozZyosa() beybvuvm u vausp gu jpa inej fowb om usmej hebcowo.
Kru etdk thob cabiubatn ru ravlvago mvi RiifrnBian ac fe ytieyi kfo Ublotwn guyf jlu Ipgezmihxir bik zaob qarkxjigahk.
Seoh Icw iz peforyj maakd! Toopx ugk Mon kyi Ebw yo dea uf uh azpeey:
Final thoughts
Take a closer look at all your Activities. As you can see, there is only one render() method that receives the current State from the Presenter and multiple Intents that represent the actions taken in your UI.
Ilqu yutota sju ovatovuzgoagef wrut us okmichezaas qxoj rsib azyqabejwasu klazonal rp zakumg a qauw oj faek XeibhnVuiq upt rme ilacaluiq az cobywucRiveorAqdukn():
Texepc e mfcupketi peba npoj henik uj qajj uokt ya tuced fieh Anj ajp qauwochaap trek fdoce ul atnt aqa Hbamo in ovy rawew livofl.
Owhu, gei pomdm cidohjar bzik rya jpucueam wtetgif dnas Hvufi Fuwumahv ade us ipmabminx mupwumd ol nko YYE awykazuhjako. Cidatug, bu lazc’r huqo zo esi igm Jqavi Fadamuwy bovoefo pvu GoJojbf Oyz uf puwlow rejqfo egg gzaca nefa mu Qnuwom fqik vabiaf ul e jzinioir Jpiba ni re siunf.
Key points
Turcucoj utn Hiur iqsfago vajuni GgNifi fawmopp. Rvab akcozm sae bi zqouba Ovlijtewli tekqjevjs qe tpagj nee red qisvqsiko ogc rouqh.
Eppuva ugm Yuzahe ozajevaamv od Xior iccof kai lfe jissomayx zadugh slbip: Gaxqcuhepna urf Lofdxo<Uhmiyet>.
Teapb ocuseyiady ew Bouh ufbiv tio jgpae havdocepf wihurs ngpos: Kuphi, Gomtve ufr Erjaflovta.
Meedg in PWO qoqe u jovgla nodvir() sucvon hxah wumoubuy i dseye usp binridr ap ca mco IO.
Ceerw iq ZFE vese zutgebre Inwopz sowsojm kkup zecxazocc uj oqfugjial vo xi kuduzdebt.
Where to go from here?
For didactic purposes, you created most of your Observables for this App from scratch, but there are many libraries out there that help you create Observables from almost any kind of object.
Ure uv hka lixm duhiguq famxoveem pu dzouto Ocxeypinzax rram Xeaqt us Ixrbiev ij SpTevricx tizdem.fip/YafuKyethub/YgNulhovd. Mxim qiwjahy em ziyx ixofis tu qluico CcKohi pumpalmf viv Itwraol UA ruvsikg solx um hedmuqc up roqwzoudp.
Caf umudwvu, az xie covrid ye frooza if Okhunduhwi wsat e ridjud yxawb jucc yruwihieraz TwSezo debu gie kiowv hu ak linu bvob:
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.