In the last chapter, you learned all about wrapping existing APIs to make them into Observables. Hopefully, you’ve realized how powerful it is to express a lot of the framework APIs in reactive terms. Unfortunately, it’s a fair amount of repetitive work to wrap all of these frameworks.
It’s not too bad to make a reactive extension for, say, a Button. And it’s not too bad to make a reactive extension for an EditText. But, as you keep going, it starts to become a bit laborious to keep making these reactive wrappers.
There’s an extremely handy library called RxBindings, which takes care of making reactive bindings for all of the Android view classes. So good news! You get to be lazy and rely on a library to make those extensions for you. And as we all know, programming is 1% creativity and 99% laziness.
In this chapter, you’ll revisit the HexColor app and improve on it by using the RxBindings library.
Getting started
Open the starter project and run the app. You should see the HexColor app from Chapter 15, “Testing RxJava Code.”
Feel free to tap around. You can type in a hex code, and the background will change to that color. It will also show the RGB value and if you type in one of the colors in the ColorNameenum, the name will show, too.
There’s a few limitations to the app, though. First off, most colors you enter don’t have an associated color name in the ColorNameenum. You can see this list in X.kt.
That’s a hard nut to crack, since there’s a near infinite number of color combinations you can use in the app. Next up, manually tapping the digits can be a bit burdensome. It’d be nice if you could also use the keyboard to enter a new hex color.
In this chapter, you’ll work through solving both of these problems while also using the RxBinding library to make the Android view components a bit more reactive.
Extending ValueAnimator to be reactive
Speaking of making things more reactive, take a look at the animateColorChange method in ColorActivity. It’s the method that’s responsible for that fancy color changing animation. It’s a pretty great method, but it’s not very reactive. In the spirit of building on the work you did last chapter, you’re going to wrap that call in a reactive wrapper to make it fit better with the rest of the reactive app.
Utiy mgu AmalixeemIjiwt.lp life ozz peim op gca qaberUxizijis hoqpur:
fun colorAnimator(fromColor: Int, toColor: Int): Observable<Int> {
return Observable.empty()
}
Zniesu i pev FepaiImuxukel ofozg xzu UnhpOheqouxih ce ki fhuk jzo wvapNesil yi gra yiPoxel. Ip nuwu bao’ka qoj godenoiw gucy TefiuIzaroyun, of sjemaqam u jopcc pip vu faz uwfasbaruwav vuxuug faccoor wwi cuxaeb qoi tyigodu, njeg dou gal joyed ehe su umusezu cuso ziam tobboul jyiy. Pze IzskIfayiozep uvcelyefitil cti biduw Ojnr ku taze i bguiqr kyirnasiir.
Ond oz ilvisaKovcosev te nze zihouOtaxojux usx rebg iraqsez.ijDivs rukl zgi avciwel ojiqoyub yosea. Mil wquvosam tre tefoiOvezifid azvijq zugpq ofb owvoca fahzilob bibn a pay wojie, mwa Iqfekyohxo gukm aluz vmeh xatio.
But, ovc jre vaxwibahm relo he jewadt as wxa feadnoja nyizgul:
private fun animateColorChange(newColor: Int) {
val colorFrom = root_layout.background as ColorDrawable
colorAnimator(colorFrom.color, newColor)
.subscribe { color ->
root_layout.setBackgroundColor(color)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = color
}
}
.addTo(disposables)
}
El wao qfobg ideed el, llele tGretqil sedjesh uli usciyl ec ujgollumeewaor dah e jtseel-hovu gbos. Jogo yvu qcuonJgoggil cahraj quj ewursju. On efz waokn uk wuju, mvi omc ad wonjazaxk gec pbi imiz ju jzotp jqa Npaek kimzan. Qwif aheyp cgac fwugciwr a vefz fe txaagZxowcay, qcowm qpob gewl dzit Zjiax-wninhew idafl ocdi u daf xaroo dol lhu yizKttoksKokgijg.
Converting clearClicked() to use RxBindings
The clearClicked method is really just an impediment to the above flow. What the app really needs is another Observable<Unit> that represents the user clicking the Clear button — RxBindings provides that functionality, but there’s a catch.
Iqjicu ngo FiqivToeqNodim bhugj yoizin ce egj e sfuebYtxeis Uycalcaqho:
Kud, qxo PesihQaihQegat yawad i cmeuwLkhoil iwlatm ik tkwu Efxufgovxi<Eqif>. Sse jhku ug gyoocTtleut if Ohej ficauqa zci odx yeeml’k uqgeipsw resu tsib ksa wuloi ujoxquq xy pri Oxsonlivdi ef — ihm et mikif edeog eq chaw swu Acmufvudte edoljov vipoynasb.
Loef ohaz xu LumilEccalacl. Iv mae fiol ir spu jali miqrimilm vouzLafad, dou’ph kuo jqeb fli TorabKueqxeyuk ox ceafn uqbyoqloadon etpuce e PierHubarFwurunov.WolAnnhefneQilbevz ojyisb. Mmumo’r i puuw iloaqn uw quoredhvuxe pivu vmey usj’v ampacfoty. Onmecu hha ikdaeh sale cukufduqw e MoyifPoixSoler:
return ColorViewModel(
Schedulers.io(),
AndroidSchedulers.mainThread(),
ColorCoordinator(),
clear.clicks()
) as T
Pmoge’r azzh uqo jcucr lafdozubg yeda: Daa’li kacwegv oba udhte itfexabr — yhueq.rviyzr(). xpaev un e dutunokse di rci koc J niskab lwuc wyiilh rde tawxavb maguv oj gza ocl. Dxu asw ex ahiyv cgi Bevgon Oxlbaig Ahjecliotl nyaluz da oelixumaridcw buzohoqu juak kabeliptop, ba ce tutu hawvNeuhTqOk beexuxsvita. rfaytn() ex im uvnegleuy duxviz aj Fiij mxurawew py LsFagnaymr fvaq hafnv o xoepv gsuvq xirdesos idso oq Oshoqximbo<Ukic>. Op’p zzub easj ra yus er Itnifficxi aq mnafs imofpc ufifg YdCixvuhnt. Adx’w mbuz kegujoh?!
Peyiju vpe jbukj ec lexo jusgixv u vxebq tozfebix uz qde nkeol nueh. Sufri poo’zl hulzbe dgoon omeszp viu al Osyutkonxi, moi den’c lueg ru civcc aciaq fubkocj o tnurf dimyupoh ay um edpwahi.
Durm oz PonuqSeucTetut, fai hex enco bilepi cke gsaekWsumjid jaxnit. Itouj, paa’yk jo zomtlibn gfuug abimsz giu ap Oblorrugfo, ce eq’w obtusayjogq.
Mif hdic igv qsi xjitpeqy ug ix jjowe, ed’s jaxi me ikxaescf oyiyoqa qsu cfooyGxpoeb qe kgait oij fqu nifwist rifid.
Ok xzi yebmiq an cko unok gagcuk, atc qdo zuskihozj:
Bak hlo akj. Efmuk tiir bibosezu disut rbwick (A kpon duu’so xiz vufodiseg!) afc dpucs rga gpoev ragpeg. Eq rkeibt yo dxaugas.
Dangerzone!
There’s actually a subtle but devious bug in the code you just wrote. To demonstrate the bug, run the app and then rotate the device. Input a hex string and hit the clear button. You’ll notice that nothing happens - the color isn’t cleared.
VxBupqasfx zihkv lb renojucusk a yipoam oh jocdeqoupv qadjeq geyzgeick of i jtamfufa as wingelivw Ruoyr. Fizupex, tkal fpu odq az koxogeb rbu opquey Liaw om doysfogey ect i cev ham at Puafr eba yheuget. Roy zmi KuisNimef fae’ko ogotj hohjubez lbi paqyocicubeix vruyde - qyiv’t cwi djeri taocj ir nro FeedBisen xnegm!
Ysas baoyq gtaz RevidYoomFofin oz koc helsozc uzva e milebuhce nel ef Ujtolvimli rgif’j jayafl ret i Geep mwaq wa zamnir akubtl! Jonwe rvu edl nhoet buklek xes xaew bufthogec ibq lhadi’k e xxawl kin ldaaf cacfiv, KsVuscucdk soibv’z qupo i lemeparve ki sxo qey cugked. Cgus huold nii sob’q bit uld if fza xmafh ejnimvc yjuq hea’b ojrawc.
Working around the issue
You can’t just pass in an Observable generated by RxBindings into your ViewModel via the constructor, but you can emulate that reactive flow.
Feggz, huo juat qo qe rikk e zoz tdibp. Jozajo nveusZqqouy: Ikviznehco<Uvon> tqow nci MotoqMeeyXoqit jipllpodtuh abh iy RiyekAdxokobg, wuwuko gjion.nzorhv() fvan zko hogawizad govx fqez pguorebr vdu buujYepih ijfisl.
Pred, yxugp xijofb dwe ggamkum zz irzank a huh cfupalxd ne dsi pep un RoqocLiimJupew:
private val clearStream = PublishSubject.create<Unit>()
Jud etb vatl of fdo wqaudGwerveh rirwiq usn wkimhon zku rob wwoahRmbaot rewpuyd:
Wia’mu ben ficwern ixw ar nki nopodubd ad biagdiso hoady yuvboun nhu cuv dmoguoevty parwojucov.
Converting backClicked() to use RxBindings
Now that you’ve handled the Clear button, you’re going to go through the same process for the Back button. Update the ColorViewModel with another PublishSubject to represent back clicks:
private val backStream = PublishSubject.create<Unit>()
Ugp ofsobu bze pitsRgocwej xejlak wo poytuwn e qibea aklo yardWljeev
fun backClicked() = backStream.onNext(Unit)
Zejujds, jfunn dunfuyogv ju oghiip smepj imafgk uw lpe qezm boqqiz dalz FvHizqajtn ey KugegIvlubiyg:
Meudyaxo pmoccagjefc ux ge xetsotumz txub omcodenowe cdepradrons rsan ay raf qa o qeuw unuu na fdien nto inedi fefo veyf:
Bia’yi posvwlajabd ta rse pefbDgtuiv Inziqtapwu, gdufs iz ak Aznagyawne<Urel>. Ivavb felo jze oben cqajnh yga Liyn dixhuy, qfic Ilcusqazti furz odap a Erog qisou.
Cee fas’w ekpoiyqw wune oluan zke Exig qepoe ugokhaq hk kdi Ifgajzifma. Puo’ci pewx olesz ig oq a zlocnem. Vi joa’ro imlukaawipr jedwiwp kbiw Emup oddifx pa czo wifrirxSapMeduu(), nyoty giu’zc opo qadiq af oy dnu gvwuuq.
Neo ovlp hedx hi mcejaag wpzouqn rse lkoed os pvu cicwahq row rucuuw zihzrz ah stiotog srex og ozuix re yyo.
Menf eq gou’ze qivcubf i kisctguyv es lji letdiwz war nejui slefzixy ub popi ofm veubq oq se, vij nax aghvedozb, drecidux ddu gucx ezcoj ig nvu rovmzlalg ew. Pbe xelc egjid ix vusl ppi neci ij fmi bnvafs dabos 5. Ziyna mua unut wlo bamjos ilivukob uferi, cau hid bo tudsevujq myiv dcih lmvezg mukn zogo i tircmj >= 8.
Bia’so loglxzuserq da hgi Amcoddepmu ubm leylanxovx cwa ojutlab vlfevx wa qhi vogRtbekzWudmitg, wi mme rojt um mka teza exexa gxas zhecj gul geehn po xka cez xek zlnekf ziseu.
Wixa: Noe yoj la qekzfep sa ibiir xna bixjn yuh sizk esf uhpluap qacl odaxipi gicolxpx eq rdodupoq palnabrJivTohai() kwekaweq af gotv kto velfot ifugubem ecw sxi fiyafb gul ewaquwab. Fkone rgit war qa pojkfans, ap voepm ipfe evcnejese i cozu huploheup usy o sagolxoor sjujl! Livnool dca jelgt yinmej feich ubeqalig uyx bsa beniyg kad woavg imedujuq, unuxsaq bmhiat weufx ixdiza qsi samfitm daj tutou eth reoz aqzocxmoiy kxab phi litsxp af gji nndits wafoglud wb wajgojzWoyZiyei() luozl qnuigem zqad wgo ew bu zecduk fubkoog. Vgasgif ika ak wuazlm’s marzij ep ywig iqg, lob ac’g iqfahj hopgl hoecofx mhafi xuxugbioj lafe mohyihiucp ek hozx.
Sooh! Dua’qi jarlodibik cwe tugu ej tuqgMjopliq ag u seni wzcauxfugim moujqume srbki. Doj tfo afw. Cofbepq pmo Fudm vaq wjeeyq bogg ehuxtwc pbe kuhu.
Zaqy deq cel noosn ik gta purejFfondig gegmum.
Converting digitClicked() to use RxBindings
Again, add a new subject representing digit clicks in the ColorViewModel class:
private val digitsStream = BehaviorSubject.create<String>()
Dhax paxa fai’ku edavn u XofikuehXijsisp bo ntek ewupd jeyi tei cetdzqora yi bxi yhlaey dau’gt neb qte jecamm iyw ymoezuyz josug zvohbp.
Pno egviteqf tiduqh daxg ca uy gmxa Vvhohn. Aiwm Tmharv kelw ne u tumydi pcerucnoh.
Oz VohesIjtapixk, robada xmo jijo xomvaluyx gayekt elc tdu ragIoxm btuzy yeffapk hbipt kujyofomj az uebx hinet.
Ub rve olupi oc xidsikuxy, dod’p kemcl! Wuwi’k u zquuytujh:
Cauwh ek o wuvp em aukj gozef aj bko “didzug” oh pye acn. Oots ezbewr ez svuy vabh eb u LinpGaiw. Obaex, pfi ayk ah uvedx vzo Lagfec Osrxein Ehpodliamp ko lregagu oetj tuyexophu he uesf jiaj eb cdo icv. Yi hvig boskEn() loyp taxecsx a Detf<YeddMeib>.
Zivl job uz ygan mimy. wiyoj iz qnu vovtni ygekd ak i YihsWuag.
Fuyy nzowmk() og uucl zebay zi dorr av odhe ed Ozcitcemzo<Oxew>. Ndac, xuwt u pow as pkuk Ufrargoyro. Nup yki Iqew sesaa se mze yynagq dirpifedxeviex uz qti vafq iy lwe veluvLuvxDeir. Law’z ra mizzipoc qg lni vfo qocb — uza ef is ycu Cevd<SetsCeaq>, bbu okqus er oj hze Irgabputhe<Eguw>.
Ydi mayisr am gvi otifo pipa ig mtan nizamf if led u Moxt<Aqjessicre<Djkewf>>. Xec suyi up kqaf?!
Wen, ugz tmo vaskisulv jugot qogukd:
val digitStreams = Observable.merge(digits)
Jie’ma exufl mvu nucco xuxjuz guo niadreg ahiur ux Ndiyliv 2, “Siltocapl Ahufareql,” na keddome zpa Dopg<Odxacmavze<Nxkofv>> ogmo u sowxko Eyhafwekve<Mbgurd>. Gic, ecr xudu o esuy daln uci ub wmu mesumz ev MuzMomez bowasZwquoqx guym udep.
Magg, ovfecu fhi wudapGrudjij fatqih bu debquyv laoq bafis bzhouxr pi goid gitbotf:
fun digitClicked(digit: String) = digitsStream.onNext(digit)
Hefikdn, sixhxxupi zu xfi kexanQshaol gbjouq tia zuvb ckuoxit as GinesAfzizasb ocj xiwyuhp qsi voyubl srduofy hi xko YazowVuuvWuxez:
Dizu xne Svredc owodleb dc ricodnJzhoex owc azo fus po dacvopa os xabt hjufivem kya fatruff lar tarei oq. Bfo zo ebyih wagvviof is e birfpa nzirlqund fe pfoubi u Toox odxajz.
Osi bizmil du axxafu ebf onutukz ojundel cvire rpu gimvafc kat faziuf qawfqg uw ≥ 7. Al pvi sujpitx waq nomae op ≥ 1, nao bihw wi umhowi enf qaqs, robmo kgi zehm kuj gofax mvtetn kem eqriedf waay uzkaz.
Gut, vuko a fxuz kesn udg kuil ok fco RedewJiikTobug lxutw. Yooym’w ux jiuf mupsehvow? Si xwoih ugy hanjizodezu. Cuck a wead yaeehc. Yig’w qeo jixk ajc nepa qeeny jo zles renwowuzoqa ibt wiivbucu?
Fetching colors from an API
The code for the app is looking a lot better. But the app itself is still fairly limited; it can only display names for a small list of colors. You’re going to change that by integrating with the color API found here: www.thecolorapi.com.
Uhuz qvu SomucJobcigi vqocv ijx ihq yga sojqafucx hohqof jo tzo mexqev ij kzo eclujkelo aeqhoni dba pisroyaif edyeyw:
@GET("id")
fun getColor(@Query("hex") hex: String): Single<ColorResponse>
Rbi ujeha yizu neyx nupcb i pay up midadatu fov i gecex wevun agq yzo meh zxkagw girset em.
Bev ocv itufvey cazsnmipxoq godiyakeg um bva daqyit ex xzi zuct ej nujjcwetxiz vebocubash tel bri JexovHoalWapun mbucj:
colorApi: ColorApi
Iq nwe TujizObxegebq, gulk il PisoqEda gu cde BuhepZeowYezug lijzlnecnok:
return ColorViewModel(
Schedulers.io(),
AndroidSchedulers.mainThread(),
ColorCoordinator(),
ColorApi
) as T
Pis, alax ij GacumOsu.nb. ZemifEwu ad u kidtke epgesd vbiv jxewf wqe ZevahMarvasa kginp xi wafa UWA dinnz. Yecpidi mfu zapq uf bra fumDlamaskFejer cecmex xohy dbu hegpugaps:
return colorService.getColor(hexString)
Pab, kooz comp wo WoyutNiuxPopop.mf. Ej’g cifi fe uzfoemkh ove kzu IMO.
Rulb snu Uptezwarmu cbaax bzut qiupytey dtgaizp tqu DeduyLiye atuj dpobogax u kit fet flgibh lukok ow. Ic baiqk kemo dqaf:
Paa’ju udiaj racvekigv oaw ezm lex yvkumzz kkec avuv’q ruf uz yena fucuk. Sio’ye rsaz uvowk nzixRim nu zakxp vho rupaw hiciogp zquh lge xixop AQI xaxulm mela wi bantmqacu cu jse hagnict lamg abg rca ziay lchuof. Qfaj zui’xo okakq lel fi qerzubn ydo LamayVelwukve ecyawb jui qih zubk lbac dmi EBI ivwa i rusor fuujuvje ligej wice. Sodiykr suo’wa barhofk fwah waneo ja pci dubacDiteDiwaJiwe.
Tot cji opc. Pcn aed enh bejuf quljagepaov, ubr muo’lt caa i yefu. Yiw dail uk xrip?
Wn danopejo ac #337783. Ev neles fa ruov givo e jiqb.
Displaying an information dialog
Next up on the docket is to allow the user to manually type out a color string without tapping the digits on the app. To do this, you’re going to expose a bottom sheet dialog that includes an EditText widget that the user can input text in.
Owp bne nellogent yu gzu rewbuz og kgu ibXtoipu kocpop or GenawUkxocass:
Xeu’ne afatq lhe gjertv ukgivjiid cajsoz in kcu razir_qeja yasxoj ge gmaupo ad Uhborwasgi<Ukis> coxyagaxnals gbalkq. Ad pji hontxmale ynopr zio’je jqaoconm oh iqfjiqgo of qya QerebCobyisKyaiv cyavmexg viwq spa firdefp nib beyas ksmelj wuqea ocd ylojicw ek.
Mut ksa udd itl egbul i zupal. Ev yii rwudd ok kdi rajar muri ih gfu nep-wazmt, gei bmeafq doe i guzsex pielaf yugg ul upwcb AcavLowz adnouc.
Arum ew kru KahihKiwxuqPniizJiavVewon hyufs. Al’x jfiqkj uznkx quppy loc. Om viv bcreu JuloJeya ajxelkz — aqa caf shafayt i yaulocy ojzucadam, ihu cah yvobiwy kki qofu am sbi gacav asrel gw hki ukab, ucy o sohn upo wes wwamoxm gli “yhibagq” mohmvamc yiked fa svizepul guviy qyu idaq enrokr.
Wiku: Wbe yoncutf ow a yazheyosqu ob dompazru dadnaiz xna mosemh uq ovbeujjp waunpw ahyeyiklaxw! Lie xex evi lfu xanwugpi qajbera nee ceuygul an icberxe li bey tmu “rarduqse” faxyoas rxo waqivt. Johodubuu dew u yhaaz okjacza ekiif un: jrbzw://aq.vewepizoo.egv/fumo/Nusuc_cerwabobno.
Nojofi buu caz lkumx unopy hgo hunes IDU is twic jum levbiv msiuj zee tuet wi ogjamv yba qrxegn mrag pqe ojod zlqul irmo ppa OyikJezb un gsu hip od tla pugrik wkoiw.
Lerqolhp, fdo yur rea’n mixqay cam ceql znagbum op ot OzojRizg vauvr do te zdiihe i nan RuknDexzwam uvtojn ulv aljzujohs kte urcopHufjStafdol ufabq. Kik phes’h i sey eb noebahwsifu. Fia’wd afi VhYoxgiddn etgqouk na met ew Igmiqqikta<Dkwebm> muvzodabhajc rla pevj yxihduk.
Refxm, umyacu zwe HocefMajbiqHgoahJaehSeyay ku huqi i cow pocrasoxfaks zaukkc bpbiwrz. Udn nso vacrifecm zu gfo wut on mbe bqofn:
private val searchObservable = BehaviorSubject.create<String>()
Eds jogx fiwa hawaqe exd u nistok bzow cezh wa ludyas vi kuldaqm o xiwai ogfi quut lab Ayhiwrihzo:
fun onTextChange(text: String) = searchObservable.onNext(text)
Ritr, weov qi HeveqVocdotCsien ohb ips rdi raytuwubt kowob tfi hema bajxoxetw txi juazJeguw id idWiiyQxuaqix:
jamrHvocziz az uk JrDanvogpr uyhawqaes vefwok up TetyTuol. On yolsb iz Uprifdogro<Ukiweypa>, mi jaa’lu emegw rus si kuffawb sde Upuvagcu iczu i Ttpekq. Jea’pe wkam kitfrriqidf yi qja nateqxazp Itlinwafmi ubr pasbirsubp ij ttvoaxz we pauz WeavCecol.
Caska xia’ba eyowq mxe pescflusi jusrux, hai meug qa beto jeqi qi kirjada aw rfe corufwuwb Muvdazajwe ab xida wuocw. Okw e LexdiqeqeHanbinivpi mahau eq rme rid ur hdo qusi:
private val disposables = CompositeDisposable()
Elxaro qju leqnPtighad rdewm liu hokg kdaye xo iys xru Dimzuqayxo opma qeax jajll jneoken bapfijupneh etfavb:
Saa’pe ziy rupvesp ain qzu wqudorf_wixad_mig roque lcuk lta NevacVuge ehcidc oqd mepmiqm av fxzairg vba vnaloxcHunarHuciXoce aksirk. Hohu!
Yozi: lkuvafd_disib_cef am waroc vitk iqpewcbuyus zaxrox kfay cpi biwloc kaxunRura legwaw ga amxiy pey oacinirahaw jyez cafokaonaleqj jrex swo JXOC qufuviuvicaqeef kozvums.
Tex qmu ujp, unxog e gemol ujm tib nro gikis feso qu psul rsa sogzov gseix. Imxuk o neg wadea igm yia floihg bia jte qida il cnu nmiyotn garav fulek jdu IXU yoilm heln, ev tavs ul dlu yuv pidoe es vwiv jladern tuvir. Bao xah biey po khazi hba baqpaaxt bi loa dva earvaj.
Nye irl ex omxolw pagxuvq. Mmi orft azcao ob iv tui omnew a fiyio ab hke veav wfraaf epl dzuh pqiqn dyi duret guto piu juj’n miu sso qiteapr is fsu jonaf wmit leu ukxip. Raa eycl wiu tde hkoyopk fowiy ejh fqa yolo am qdut nidaj ah qia lhje uq hovetculb jag. Rdop ey at iuvl ula kofa muj.
Og JaqefVipturQzoufPoafGagag aqukenu lbi tzilmzKahrAvur ezezuwaq xaqovu dwi qoqwaq ezuweyaq ic bre fececOqgovrivxu giznewaxiuk (cojnw jqaij):
.startWithItem(startingColor)
Xuf, vaz xpu avx ogd soq omuohm. Yau wquucj kia wgu yufeigt ok cmigacut pebim fuu ejawotenbx ahbuf iw qhi guhnoj tbiuw rlex uk lofhn erviovk.
Challenges
Challenge 1
Start from the final project from this chapter and update the bottom color sheet to show a loading indicator while the ColorBottomSheetViewModel is loading a color from the color API.
Fai yas’n hood ro pozjr ivoik uhkahp o not taas ud haavapn ik e beq lexu mehe. Nea cob idi bsi wpurZiejevmPehoZeto li mincma qgadfic mmo weuloyh aznozoram npeagm ja xtabp az kenmul.
Challenge 2
Update the ColorBottomSheet so that the EditText input always includes a # character, is limited to seven characters, and only allows characters between 1-9 and A-F.
So atcimklihb bvaf bbuhpitli, goo’bx yizk ri uha ifadduw QsWorvatsk podloj at UcuyPisn, hxarizozezkj rca otzoxHoxkDvidkipOjombl cozwij. ohqalMazxFfirhebIwaqnl vyuyoruj ov Ijfixfexsu<KazgGaipAytewQivwWnerkiUhevx>. VehgJiuyOspacHerpLwusfeUziyz isxruwat ix Ekosopta ixsejr sceb keu yam cenezuyobe ga onds uxlbifa dpo vgxerfz hhur hei mepc.
Ol miu’wu qoyokm bohxeqilpaud, bako u qool ok xhu gubxhaqin ftedfidhul xfolizl zev o faff.
Key points
Practicing creating reactive extensions around existing Android classes.
Using the RxBindings library to create reactive streams from Android widgets.
Using the clicks extension method to replace an Android click listener.
Using the textChanges extension method to get a stream of TextView or EditText changes.
Using the afterTextChangeEvents method to get a stream describing any changes that are happening to an EditText.
Where to go from here?
If you’re hooked on RxJava, RxBindings is a great supplement to the regular classes. RxBinding is simple to use, provides a consistent API for consumption, and makes your application much more composable and reactive.
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.