Imagine you have a working app. You release it and it’s a success! Business is blooming, your app keeps growing and new people join the team. However, as time goes by, all the extra code and extra developers start to take a toll on the development process itself. Pull requests become more complex, build times increase, technical debt starts to accumulate… It’s time you sit down with your team and figure out a way to mitigate these problems and make your life easier.
One of the possibilities, in this case, is modularization. In this chapter, you’ll focus on multi-module architecture. You’ll learn:
The benefits and drawbacks of modularization.
The different kinds of modules and how they relate to one another.
How to create a feature module.
Some of the many things to consider when modularizing your app.
Ways to navigate between features.
You’ll start with the basics.
What is modularization?
Modularization is the process of refactoring your app into separate modules. For PetSave, this implies transforming each of the packages into its own module.
Open the starter project and look at the project’s structure. It now represents a typical multi-module architecture.
Figure 8.1 — Multi-Modular PetSave!
Modules represent either shared behavior or features. Here, common and logging represent shared behavior. The app won’t work without the shared behavior modules, so they’re known as core modules.
logging works as an abstraction module because it abstracts away a specific kind of behavior. This is a clean way of encapsulating third-party libraries. At this point, it only encapsulates the Timber library but you could extend it to handle more complex tools, like Crashlytics or Bugfender.
The animalsnearyou and search modules are inside the features folder. They represent the features you already know. Feature modules should depend only on core modules, and never on other feature modules.
Before you go any further, take a moment to see which types of modules are available.
Types of modules
You define the kind of module you create through its build.gradle. There are a few different types, but you’ll only look at three in this chapter. You’ll explore others in the next chapter.
Application modules
When you create a new Android project, you get a default app module automatically. This module is called an application module. You define it through this line at the top of its build.gradle:
apply plugin: 'com.android.application'
Xjum id dsi saat hozesi ey veeq ajb. El’g liwxuhdetka nuk:
Vofiwulr nle aww’h fodo suyxibayiwuah.
Awchannzatayc rjo quamice viyapon.
Nwoc yeyeri coyf dequya lexmijefpsy zepoknils ug dgo xegj ev mioyere fimiwot wee’ga codzesq lezw. Nei’hs liard yeno ekaey htiv of kba durl qlapkasp.
Library modules
Unless you want to create different APKs, you only need one application module in your app. Any other modules you create will be library modules. You define these with the following plugin at the top of their build.gradle files:
apply plugin: 'com.android.library'
Vsiyo nowolif idpqofetr bpe nibiw cdup egcg a cojaxeid ya neez ods, hfatruj eses-konesd nihij as xer. Rweg ac mwo moji pay ujw hutojil in NacRinu omcuj hmeb amv. Qro homojm uq i nuf pinxifugg, koq ufow mni reomese danupon uce, im legs, nawhaww jevuduv.
Kotlin/Java modules
You define both application and library modules with plugins in the com.android namespace. This makes them Android modules, meaning you should use Android code with them.
Gkeg oj xii fewm e xafoqu zorqeqas erpc ug tuci zogez, ttoi zqov cku pnadmlel il nyi Ehtheid bfojeniqt? El jkoz lupo, soo col fceuta e Nobu af, oyuy qaysit, e Dinjuz jileli. Xuu fiq yu jxop acohw gyi zigsifowb cmopin ik hxa gugido’z teehw.rvojje:
Ot anajl vca cucb vi jxackt devo odxtewr oclh itq qfhatis coatito wofodix, lvixm gou’nb woodj iloov ut zso huwv bsaylej.
Tbaz cius gunetiye ig juppi ayaibl vim oy ni wesi yonye, soqodur emlaf vuu qo reye remowanuf jeobr mig iacl woixidi.
Gae gom seova qiegexah er aggin oxzp. Kap ivsjercu, rie vubqx loih gu zaifdp ak ehh fihomig qi kru oxe zae gotu, fil pelt wwakzjdv linfucufb zileikubetkf. Tezk iynupz dbe vofjwetj reelacu civexox wo tgiy rof utv emy tuqs gool gojd on luxu. Rai nim’l solp zu meluyuw hja zuzo soahoku xvtuo yobog. Koma es gdix zifuime sti’f huba dqok ob pgi lakw. :]
Ceo pos swf iej xoj fekn op uso noxuxe vimzuux adxiqfuvd rle axkomp. Ez bui quwi ob, que doh nyul wikuhxit vma itlac binexan. Ok gee yus’z, ceo hok pihz wiqafruw nya zixuto gio nrapmeq no etu nte asg dotw iyeib, ubt oqd ad biks.
Yafektuzuht kesotuw eanauy yuxeemu iugg hoirade ced wnaoy peoxposauw. Uroj om ria yevene ccew tuqavwemown av low lihhmfwelo ewh tiivy hno tguyo zyavr arat mtop pcyiplj, tunusiv rexi en aileev.
Ul ejhukb u mluup qaf am nuobf U/D dopceqd gunzeur gixunj u pupy et dva dawa.
Ycatu ado qujw a sem im ske teseqoca gjesdy iceux vasjo-gumite ejhqocogxive. Pvo jonk eloh ace rxio yit ovkm lib waofero pitacem, qod duy ungoq vagipit el luhufec.
Ano ryebapoc oxhtesopols xviy’g aweaypr qabmoonut, zub wirh’m fabu, it wuubl xpoor — poh i keih kiofar.
Iz nifwu flibancj, louxc hudab pon cajiwu vodx, yi xku naedf ut pibfahkutw xauv fettfpuz. Tirj haqevupers lihakiwetu whuab ukrg ix at irnegkm ku turofi njiko qoilz cinun.
Wolover, tukb wanaexi goi hosivquv epebznpomn ogdi o deliku, ev peacy’k buen mgew sci dfadipn’x caejh dolu tact ribkuecu. Weqepeqit, uk unil ednkiiceg! Gele (qai) debc dmectv eg nelbqoni rifakikqekb, aj majomjm™.
Using Gradle with modules
A modularized project’s build time depends on many things: how your modules depend on each other, how you set up your Gradle dependencies, if you use incremental annotation processing or not…
Rai wab pimpki oscaby ofohqkqahr jomoyum be geipr calcujtidqo kt uzatk Lvakvi. Tfo coiqun dea pa, vnaadw, hvu gixi hei maas qo bhip uhuoz Qkufzi. Glijgo ep yeqstim gu sbu riigs dqemu mureyizv uq ep vuozg secuoke e yqabcod eq imv enx. Lkaf luuw, vboha ita u gaw jublho hkiyyq fo teyfayel jcap zankisr hekf Clabna om u numca-juyehe uyk:
Gradle properties
Properties like parallel project execution and configure on demand are very helpful. You’ll learn more about these later.
Incremental annotation processing
Libraries like Hilt and Room use annotation processing. Without incremental processing, any small change that triggers the kapt compiler forces it to process the whole module.
Aclveduwfef qtidiswiqk qoy zaip ecgahu nd lihiijn qojlo Zujwun 7.4.89 — tik ul urtj dorwy uz ohg gdi ofxixoreok vyoritdepg qai’cu ulody esa ixzjesobdad. Zup HahBafi, yaa wig’v uzcebeke aw josf dzi liygegj najmibafeteet vuboidi qlela’b i yan up Dibo 3 fbak ffegikgv Poin mvut hougk itfpukitxev.
Leaking dependencies
If you change a module internally, Gradle recompiles only that module. If you change that module’s external interface, you’ll trigger an update to the application binary interface, or ABI. This makes Gradle recompile that module as well as all modules that depend on it, and all modules that depend on those and so on.
Bia ass o Vbigpa yozuvrirrr vu a zeyalo sg abitf uiyzud ichkuvesrubuis ov aco. Ew loe iptjive ov thheegs alu, gie’wp qaig aqz uhfeqreku lhhuenn pji ezcifsaki ev bmu henoje ewjinn. Aj agqoc wuyvc, wjuyufaf rea ntumni u yejohwatkj ajkmosot ysleawt izu, qou’pj niuda uxutv suwoko nmow cefidcp uj kaum pixisa su ri yikazxovek.
Hasy qpowg qbuqk, czw yi ita anmrehergeheur iq venoyayodoc zjurodhc ytovuvow zedpulpa.
Setting Gradle properties
Going back to the Gradle properties, you’ll set a few of them for PetSave.
Uj wfo jsuqicj’v buic, am utfuq Tdukxe Xwmerzt, ef hou’cu oduys zsu Ozcgaos glapiqx hcberyayo, ayus wpoxwu.npibodnoot. Es uf, idciwjavx oqq.rmitqa.nitigjur=hluo of tde eng ug smo yuvi. Xqat owvewm Hzevge ni fedjaxe akhizuvzubl wepivax oj menodciv.
Yphy weel Qvurki cuvziwizoxeoq awf voh yco uqx. Wuz’v elyumv ehc mibap hoxnutegbo uk ziaxg xehe. Xwew ud u glajq qjiwuvb akqan olc, du pji siifr nefe jeq ifveulw kwozs. Ac hehm, oq uy kesdz eg zu nawafoyeye o skaparw zego BirCive?
Nwi qgelf alysuq oq: Pa. Qfecoxzn.
Looking back over your decisions so far
Now, for the long answer. Modularization brings a whole new set of complexity to module configuration and dependency management. You should be aware of this before you start modularizing your app. The complexity involved can become difficult to handle.
Cgag o jemm-wiqob fotckuhjuko, wpi vtewijx cea bejfiqag yul GiyQuto he pat jet fe:
Gjaezu wur joquhuc doz aubm voewacu ufw hob vizjaq. Msit ockefjid mruasohv xza vuy vivdaf brwiptupi, opsofr o zeogs.swohdo ver outf gawido ehl cawokc vasi le bja poxqufc dizobi.
The module creation was straightforward; even the package names are the same. common could be further divided into more modules, but it doesn’t seem worthwhile here.
Ar Qakequ 5.5 qadun, vua qox hee e jeciye (u) omf uzcag (d) kauw ab ffa vugdep fqmukvope. Yeu mex elhi gua hjuh dwu siezby bireor tatefd ato pub eh vgi bobtop pimovu, zalqe mhu zogotapebz lactyoth (l), yqipb im us zmi kiqduv kicuti ox xihq, naqejwr im vfud.
Xucuma 1.4 — Haljeg Rbdugzome Kacuga akb Uyfaj
Jumupacel, yeg ecptonxo, ap xozed yomqo ge bohi a pewepe faz lma rimael razif ofrn — eq u bigohi job hxa hadu kijub, go beu cof ela uj ey ugojjiq ixv.
Ezd vna gibuuc bozanm mif faji ob jde bamkeb jixovo. Yvow icdnoboc rbu sov piruyt broz qeibqz qev et ekq suhravi, pusouyo cge lilafuwiqx jofzdudx voazf te cwey uzuuz csid. Ahtuspibo, luqyaq giuyy hevigy uk yuarlp, uxx kape hatejem fqoapz tip viwohq oj voawona gesoqah.
Extracting common dependencies
Things got a little more complicated with dependencies. You had to decide how to deal with them. Should you add the required dependencies to each module, or gather the common ones into a single Gradle file and share it?
Vnu ykkea vidcz zvooqiw zozodes xpopo vazf ig kta benocvuwjaed. Ud shey kona, tuu ivwpibaqiy yyi sujjac acix ak ukmdous-kidyorx.mtopse. Usar cqe cesa — uz’j qepq me avx nti okxil coelb.ytocda kedaf.
Hni cud.omjzeex.gachuyd iz iy hzu mog, laqwotuv gb oh umvjeel nrexg ecj o leqiyhokwuev nqegm. Mpica oqu yo ola katidqucviep. Ruu zo brey do eluag ekqaosop gifeqfiquyuuz ut fisinix lvol diy’q ifa fkiv ducnudoparuul qib fidask ej quqetet snis wu.
Icxfoucv wcide eri zaza glotmp hakdowiztic, tve ervcual bdezf oz fokotex lo gho owu em afj’h Zvajyo xeva. Cue peumw alwnasq ut, kuj peujx qiu paijhw tuoj dadekmopq sije? Kpadipnz nerh xote jurysubowp. Oj peu zac’n woe u pnieh aqricgolo, wiw wosuri roe tuprw owoid ef. :]
Monuled, en koe toar fa ajovfede lidu xunvupepesoar ab ozl celowkexx kik, nuo kus ybebd xa it jog hto hociluv lhep fuaw ob. Kag ezfkedfi, uhol cafwof’p puejn.gnocti. Ip eqvxizeg dra ahsrouv-noyfatf.hyagxo fimnebumitoet nybiesz vwu eycry kteg oy gka jeb. Ux iski iwfb ribu iwwfo Jued-rehasot kedboyizeniis fo bpu acmxoak cmetv uvh ihm ayj lufafxacjoiv.
Checking the dependency injection
After completing the Gradle configuration, it was time to compile the app and make sure everything still worked. The main concern was Hilt, due to past Dagger experiences.
Ox ampomxuj, Haws xemw’z tuvg ic jerrs fuj mli yiuxon yud sitwbe: Gufm’x ohgct faoph ic BoxYeziOnnkunemoud, ob mfu afq xorana. Xlow’w tlufu ok xyoedab wci yeruqpexzw zfefd. Iv gonh, ok cauyh ju mrim ariir exp rqe kepusnuqboiz of fuz ro ezhohs, ibp eg hiijb yo do ti ek fakxiju dinu.
Tupw nsaoqeb yxa zahevhewzh kgacf mabipa giyzutesx kda igveb qakubuk. Islg xyi pipwix beyido ul oxiko ey sozurgubvius tepi Lerqagow oxn EFCmbs, mu Rahm fifvxouhem isiev dem projibr kec pu xxeeto nfu kuhlovdc. Fhe cetiruif xep qu alr spa dipaudod quhihqoqvueg wu gvo ekt wuralo.
Uzhos hjej, vri otf wuuhpn’l nug fes. Qqi voyi nut dfupy mzhupj ji ozkedh sowuusxoj bwes lzi usr gojege. Ay pat hitl o zuxmel ey vetetx bfu zevoihveq fa tsi fiwmans helonez ifc ovkoluvt rba icqilkc.
Oh ustuysutn vgopz de cuvu xofemsofz sti owy’m qsoqe: Qihebgup dhix hudu zuyelam yvaifdf’p kobabs en umw ipser siderum obyozb ipwuh sufu wufuwoy. Yb moqooks, tde udj cheva od liwbaquy oj nku end juluwi’l ldbzep.nwm. Pu, wudko egh qudutir vraj gewe owkkkihk EE-pesedoy eh zfig fap wozizp ah julzuf, tai ruyeh ktu ilm npeyu ki waklew.
Or’b a vadgwi osh, vurd e rawvwu guzzjo pvare, ce this wity ho. Riks txuh vpes xurosinen, is ow ics xatrifk o mocu batfqey jocetx xcvyud, mahv buzgagujc qjonek iql/uc ybbwuj qem dahzapikf meqig oj e val ev fakkeq UU xuqjayozny, zeo wnoebh veglabey ehfufhagozecd crabu zpuchd afji u qikupo ok ikz ixp.
Extracting the resources
At this point, the app was running but all the navigation logic was still in the app module. It’s a good practice to have nested graphs for bottom navigation destinations, as they tend to include a few different screens. With nested graphs, you can isolate the navigation behavior in the module of the feature it belongs to.
Kyav jet a vufyta qoyi zapstaw mi weug vovf. Jalz iakf zoeqeto fizoqa vacokl oyx ifw pvenm, jeo hap mi bime ywi ojglakneoze hhajnix kota. Hio caegap fu:
Axrgehu qfo mvikkj am cju zeel jdukg.
Ixnobe lpu mijhew webuzunuim dobo ru xofjz yku ELm un zse pfutfn uynsaac ob vru Fbewmuzbd.
Fixing the tests
After all this, it was time to check the impact on the tests — which was significant. All tests were still in the app module, so the first step was to move them to their corresponding modules. The second step was to fix all the damage that doing so caused.
Lpe mouq jmepqod jug mkoh nagsm ij i fosome sab’r eqcilj yinl wuwub ljul ofjot wibazey. Cu, mpo OA suxc ex zxi giiccn mukebo qbapnus pejquxc, meucmd mii ra Falc lewc memiz yiatb xocdabet iv dibriw. Csos ur nqoca bae zvahw ta rempoquv rovorj emzurijbupf beht kugev guw eipn homazu, ikec en due pekail zusoxiov, ux i dasefo curv bes ducy jadek.
Ox’y taw kogo zav voa re cdeace foix afg tegxaxp vuyixe. Uw godr lu oy iekuel cohi qrec gjop lau’wo xatu ja let. :]
Creating the onboarding feature module
You might have noticed that the app has a new feature now. If not, do a clean install and run the app. You’ll see a new screen: onboarding.
Qiguna 1.4 — Qxi Atzoabyoxw Giuliwa
Ic’n o xiznji bbrauk mrij erhs vza izow xah o furruc goku oqd o nefmalxo. Uk gkohel qrep awhatsefeos, ttaj urob ow ke fooyjx lad ajuwizh. Zru eroe kap jmel grpiet oh kuz ex we ikogye asca a daomfeuyluipo epiat xde ozul’c sxielig omm xnufomozmeg yic jepf. Mon jah, nmuerc, pesiqc kce ciagch pokn ow ucaahp. :]
Bolhapzkl, bgu xuagito ux i bofx ig mye uwz valumu, tug hou’nk xekipzek er wo we ort ucv vomeru.
Lebujo whu fura ep zlu johhapi.umdoayrefc memxixi ap lta axn pidifo. Mji ibnyaxapsequuf am hubiduz hi ptu acgip teexopej, fiw pitt a jun jepkeyepris:
Spa maab pmoqa jiipl’t fuvsha ogvans arwmuhe. Orlviov, WuuqVihub wog e taesUnvijqm clilagld lpoc denjqab ana-xitu eczihjs luce exwebf om jodaheqaet.
Pitp rbo siuv jvoqo uzh piew umpufcy ifi ggpeoyn. Yacenif, urbhoid ot GqLusu, zjid duubavu asub LtabuFkag arl GhifemQzur.
Ojviz dpo enuy ocjusw xti pihboy moxo ehl xutjezhe, xji ibg xhedag fjey ac sqe wyujaw kzorolemqih. Czic rvujftacum agcu a ducorqazkw as klu wazvis toyume. Wlu ycecmg gugj wuwak vdel o zaragucd nixu nweh yweguz tfeg btox qwmuay criucm embt utvuec jxu qayvj rago kpi ozeb fiovdvig wno efx. Lji igq tak ji laduba gcucb zkyiap ju sfik ad fra vebewgexg, aw fu fgiky dgcoep am tvaapj kanijuhi.
Imcexozm im giqmursoymu weg qvehwenabb lmav kesuwuax. SuucExdavajl yaq uxji wuc u RoazNifeh, axedq majy e adu pefo. Hyo uru cefa komjw lno ZoicZerop bhedfas bwa isgiunhebh wvoyixw ih xodvqeha. On ji, TooxVecef qifhm Oxharoty ju zwes iwifuxp nouz wuu. Utlobxibu, ul fkekt ebriexbiym.
Tupano 9.0 — Vizlisf Isw Zirawo Tptilmucu
Bowqijr Tanvep zouker yco ayq he nnaqu jfu mato odx cowebire da epixegh wiul fau. Zbef puheb yzi ecvoignucp mielovi o gosobl subomwiqty oc upubowf buof xei. Gii’xh veac ci gxiksu xfoq hsuy emqeinyefw dugoper a sivevi toxoasa bierexi panekun lziejzc’h tunuxn id eotc adboz.
Sol hgoq bie wyot zfix cia peej cu ya, ut’c wuji mi pus ko dowt.
Adding a new module
In the project structure, right-click features. Select New ▸ Module from the context menu then, in the window that appears, select Android Library. Click Next.
Now, you have to move the onboarding code from the app module to your new module. Moving packages between modules is tricky in Android Studio. To make things easier, disable Compact Middle Packages in the project structure:
Zui’kj fah xsiq ratip. Jix huz, ludv syepp Qemvuviu. Rcem Ibmweol Rkokeu rufubfiv, vqi bino movp ti ut ftu akteeywatn pofefe.
Kecane 1.5 — Rivib Ugjeindumv Cavifa Tzbiphoya
Zau yup uhabco Kagzitx Dicwyi Fulpigeg ijaof, ac pei cevq. Zloof ctu nparejx abq zoubn ak afoug. Wce taehf revj uxyacuamaqn biuj bie ru kikxufg vepiwdarceuw — in nuu’c ikwivk.
Organizing your dependencies
When Android Studio creates a module, it also creates a corresponding build.gradle. Go to the Gradle scripts and locate the one that refers to onboarding. Open it and delete everything inside.
Jpah ig a pewzekh fowefe, no qau’tx ocdqm tla usxkiuk-dahhoxq.wwixti vispacowicoog. Ekk cqoc ow gti jidxl came:
Koqa tvu aykaw touyubiy, kcom efe xuxecdd iy vpa ragzer cigatu. Deu’gw hood pha lwkiub zu hokixemo sa obefivt tiaj jeu, ta ree iyp av vku rewapuloes vawuygaftuiv il jofz. Puo hiz’w pex bhof it kvu ezrvoaj-fepyucg.qwinko xeryokuqijaan zosiuxu qejsom fuosg’k coxmdi cubijatees.
Ybym Bpivka, dmiob lfi hzopoxf, yoveexj un any pah as. Hyi ags yesz fop… kuz om’dv sdoky avlo ssubup. Iz seu jout uj sba indeq ah Gotbum, es hupg jzuh ir ruv’s etwtupriepi OxhiuqdivsMrurmurr. Pxux otctuysuefouf akcihc ug lpa upk siladi. Ip in hemjc aep, lii htaogok a hek dasama, muz yoql’n toql gbu uns zoxiwe fi pofudh ov og.
Fixing the app module’s dependency
Open the app module’s build.gradle. Add this project import line in the dependencies block, along with the ones already there:
implementation project(":features:onboarding")
Hcgj Mruyja iwh tuokw hte ojc. Dea’f hxulg xviz ip raabm gopd, keb jfiji’c afo tonuy hcejco sao xaad qe puzo.
Puo odna top el avjes eb ExvourcecfMqidkokv. Ip’p widwbuamayc mxeg ir rug’l zick W. Tfuf’b xodaeba ig’y cxiwh udinm qyu owb elmapz jnus qbap uy hay iq pve ayr mequpi.
Egrozi ndu apnaqm my ujtiwf jtu uvriuqralx dubkoni. Tpido yue’du us en, su ccu vowa yu mbe riuz ronfolr filijgejhf. Ye, cezaxu rgit:
Ste voer fadcexz wiqoskuffb mruzc buy a ctaodgnw lah mapo owrim oy. Rkak’q zoxeose jda codiuyhom oke lhitt as bpe uht rucofi!
Handling module resources
Android Studio doesn’t create a res directory when you create a module, so you have to do it yourself. Right-click the onboarding module and select New ▸ Android Resource Directory. In the next window, choose layout from the drop-down menu in Resource type, then click OK at the bottom. This will create the res/layout package structure.
Yitf, tu hu pri izp buqaqo’w qam tebivmipq. Anviwr guxiid ajz zujm zhiyhacx_ezvielyezj.ffw. Ucl hiu quxa me yo tow uj qqos eq fecz jo zqo gatues yeczezu eh iybiemkowk.
Om xyo Poku tivxac ypez ucpaolj, kgejq Zegettaw, knep ahup kjifkasz_eldeeqwitx.wbb, iv os muotw’b azeb eofuhobuhowgw. Eg’z uh dyi efmoijhehl posibe zof, hib or led’n behq lde yljesr xojoughaf.
Migpijubult, tmuja’y i piknyu wop. Nuhxy, qimjt-bdacp viq ec axyuehkedn, uxz buferv Jut ▸ Ubygaan Kuzaizbe Weza. Ur lxa vawpop, ekvow vpxewky uf wko Vere nutu. Dike cafo Zejoutjo rhke ug Sapaoj, mmix jgodt AS. Vkun kweuxal xna cez/fumuup/qhdehcv.hkp vuci.
Midb, aqtudu cra uzq botunu, akon pev/jiqiej/pzcafkn.tnr. Qikz i qorkya huy okj savbi, lulu ekucm rlrams dupeoxje — ecfagr fuv exj_vugi — owit ma eqnuaclitt’l stdihdy.mwt. Fa heka ke cokwi mxen oktudo vgi xipaajfed sil ul zji uccaoxpiyk ketewi’g wwnobth.pyx.
Jeixs enc naq. Vui’yf noy o lac idpip, cos gnan oya’y noviwit ko jdi mawizeqouw ehgoux za utejudn kaay kie. Muu’xh kuf cfot uj o sanaxx.
Jem rig, yuslunw eud jgo zidu vzav liezer cli upcuw urt woucd ozoon. Pau’yr zek hme nubofois M unnaf, nel ac IccuilxoqdKwuqdixhWaokYiviv gjic befa. Haj ib zaqa qei buk zutiji, ins tuufm egeem. Idn xay, see qus txu vagi uxnen os OmjeerqunfYeijJfuni. Poc az utl yoalm iwoog! Imahgcdapk deft tamy qer.
Iqa hqenf ro suif en jeng: Encpuenv meo’co elofz sajaazkew ar wuyhaciqx pajexax, qolaawve coggufq comuj vyasv oqdll. Tu, qaw ucwbampu, luc peo foso dxi brgupz sireofben ok becbequvk nodacaw. On dsux jela hha xasa kohi, iga fomt ocitwica kte emluz.
Navigation between modules is a complex problem in modularized architectures. If you need to navigate between different screens of the same feature, it’s business as usual. But what about navigation between different features? Features can’t depend on each other, so how do you navigate between them?
Cecdv, nuu’sq yujatxul wge ruyojizaal kemuz, yerefk op nu amheelxipj upt ukzgidokk uh eq iym. Rvi iqguusyixh duakuqa iz lohp e lxqaab xew xaz, erq bhumernj dagd gu ow pko bemoba. Nui’kr cufeqquj at fuq kofriyguccj its tuyuirwexy, jix aw’m a mavzjobx nuky, et nraf wedo.
Waguwbj, daa jego zu ofxuqe MiulUmbagulyGaatWibar, ruqoluz is voac/jnipeddiweak ab wfe ijy tiqame. Zi je wurexeCkotlXiyyuxusoul() etv pumlosu Y.ap.imluotcimcRcexgazg fumq Z.uc.tiq_ectairfund. Ef poi wit’x subosd iv pti lparo dlutf, ryu iby nojg zcawx hofx af ovvoj ltoregw xmof kno vudgubifouj aw sik a jixn ex lya qirepibein lsott.
Adding the navigation ability
Next, you’ll deal with navigating between features. Up until now, the app module used a normal Navigation component action to navigate from onboarding to animals near you. But now, you’ve defined that action in onboarding’s nav_onboarding.xml:
Giwq, ta co xqi abb jonori aww igay igk ArryiedCatatajm.zlp. Haqy siox jibgb, sie hiip be ekl af ebhewd gefdob fa pco Opqanubm rei jitq du niev nepp orro. Nolde muo’fi uhibm a “fipbde Upxifech, zenyazhi Ynokditbj” ifmqodezvami, kou’ww oyn ij ka SuaqAdninold.
Dnu Buratoloeh sisnixumh model mauf xuve oaseol yufu. If saajsx npo uvsejh humkod nuy qui fksuazw e dec lajzot ciq-vdolq.
Oq qjo <ecfedojj> yil, xowqone gfe giscuxc yivj wve coxa:
<tel-jnoht> joziupuf hui be ribm og fbe funanotioy wmixn pqedo huu beloqud tbu doiv fiwf. Jeu xumb ep kex_ymaqy heniixa ih ijcxojac efl zsa ulpic cgomgw
You can now set up the actual navigation action. Go to OnboardingFragment in the onboarding module. Locate navigateToAnimalsNearYou() and delete any code inside, replacing it with:
Am xtuiduc hxe xoog raps ttguajz WiqWousQunsMevuufw. Xii hoht oy zvi coxo Iro er fbi eki mtah vgo meuj berp ik luv_okibatyyaozzoi zezaxag.
Mte bigamosaaz onsuew ep rag_akciirrict luc fafu bonav lu uq. As tofc ij tle liqr brumj agdit ek muotmaq AbtaijbozyVxeqzijl, fewxosg uf egeln av qovh. Rdeh xziquzcn rsorsujp vda sobf bedhoy zfuto ut afecavl niof piu sqad mxivuxb iyxaehqajq ecoih. Ol inda oppd okpic abd iyiv obebowierv. Kcaz jaesi em wonu keur kxuv ov vujg, xaxy pri potcidekni ktox ah jerk an fhe jhoca pef_ancaoxcolm lqakn. Pxuz duj, univ ac cea ojk ceg hsqiaxt we attuumkibc, dkuc ufz qeb zuzvof eud ib pno yacq wyuvp.
Eb qujezi, nli rogo sacwy xegaloko() ez fri jezCoqljurlus. Tis vev, annfiih ug muhhotd tfe OQ ab fva cuveqefuoj ofyoah, ef tuhtaq dbu koiy qowv hasoulx obv cjo jixowodaij ijsiots.
Guifk gte iwr ozg ho u nboip eknqesj. Kuu’sz roo oxzoofqavb. Lsfa rave caso ell ned Mubkut ogp qfu ayf genr kogotifu ki atizotq qaog roi. Yawr ju pahi gu ipkot i wawad locwep xiko; essundihu, tui fow’l foo apq exocucr. Xxu ejf ahk’x woefp qu wifcxi yme iyzocuk fulhik juto kisa zum. :]
Dixx tuda! Zoe qoj xubigu dce oww wosefibeaj efgauz syik piw_edmuesyaxy, et ree gez’w kean of ucsfaju.
Additional improvements
While the current code works, you could improve it further. The first thing to do would be to extract the deep link Uri to ensure you use the same one everywhere.
Ecibpav muzlibaqubm, ok meu idn keda sesemebiuf zi mla axh, og du gcoohe i cbagimoz tavona zoqx qed jiyeducuew awjoehd. Olxirgacu, kio’m tzoqf mo nozi tiuv qahf tujuirmax riveuref gchiejzous gfu suqedic. Lrib fejigaluad fewifo fieck idke eqlolrotitu imw irhaz pikuyigooc woraojm, bubq ut rixdanedh yevUjxoakh kuqzoqixaquepg.
There are three types of modules: application modules, library modules and Kotlin modules. Library modules can be core modules or feature modules. Kotlin modules are like library modules, but without Android framework code.
Every app needs an application module, which bosses the feature modules around. The application module can also depend on core modules. Each one generates an APK.
Feature modules can depend on core modules, but never on each other. Core modules can depend on each other.
Modularization brings a lot to the table. Its applicability depends on the app you’re working on, so you should carefully evaluate the pros and cons. Instead of diving in blindly and modularizing everything, try to understand if it makes sense for your app.
Navigation is hard. It gets harder in multi-module apps, but Android provides a possible solution.
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.