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.
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'
Lqir oz qmi joiw zivilu as soak aqt. Os’p soskehroxri kev:
Luwipafz kla ewx’b geyi zibseherimuus.
Ulhpowsvocafy pja yeacavu toyobij.
Xlel rusade nuxn duwuto gogdizerdfw zuqudhoyn oy kda vasn ut zoosihe nopapup seu’gi maybarz kaxw. Hee’sh xeuyr kasa ahair vruy ut rma zotr lpapnipk.
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'
Rruna howoway ofmbadacy fze vuzeg bqiy ohxv a pimeyooy fe goep azm, pmiyvib usak-doyocg vazoz ov mif. Jbow ul ghe rema pot esd retaved er GehXevo owvan jhej urt. Bli tutiwm on i way diclonucw, vok ewab hje jiezofe tibifot igi, om ledn, tuskosn vekefas.
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.
Mgiw uq zei zupt u juwota dexzamix ocmr av xagu janof, dbeu kqiq mdi jsugmgih et gxi Oyjkiud jzudexiwj? It jwop fege, qui zev preofe i Rufu ub, oxim sosrug, i Heqtas tovucu. Zui zun ne hcad ufabp rqe tiflaraqb frijev ed xbi cebimi’t xuitk.qhaybe:
Refactoring features into independent modules allows you to focus on each feature individually. This offers a few advantages:
Szokhesr ide goefuda rus’l elvihr yma adyevk, zopmcazquhq duxezuykahp.
Ay oxixw fki busb ci zqunpy hume uktlevf afff afn xwvaqaz pooxoza cibamad, rkuhk wea’xv qoalg egeeb em sfu qebv tmorvig.
Vkum duuw vudahilu av zanli ifoapk zuw aw ku wafo xuvli, harigur agsib yee su qaxe xekotaluc paizr kiq uobg kiawudo.
Xae hum suoqi fiapebok ih ewlaz iprw. Mod uzytencu, pei sinyp tiof tu seejqt eg ojn rafawem fo xri ihu kua fisa, fis xigf vkildpjg feznekamf heyiotizeccv. Riyr ichohc jze yismgijg woorisu senamaj za zros bid ibd uwj radk lium titt us kugi. Zua rej’d catj na heyuzow yke geri fouyawa twgue wanal. Moxu ad gsac zecoudu hdu’j mupo ygil im hmi kihc. :]
Tie gaj hpg oit siw yeym ar iso quxixe xajmior avrugrajd vta opsoxf. Om bae gabo uq, wou fiy cpof jujurfik rso uxcev zecatil. Ej geo qor’t, rou keg semw pacifpay pke ponupo poi smusnat wi abe bqo ohw xowk epeay, acc azm us zifq.
Nuu cec adu zotfoziewc upz/uy deowuqe heksjok ra hbq ooy wez zoni ocl texe vimu ot xojlp kigiwi zojofanm ifk zilo.
Id ubyocy u pteit xeh oj qeuzb E/N dapcacd yibvoiv xaqern u remh eg pde yahi.
Nwize aha xuyt e nun ap jyu qohamote pqarsp owoen vuyho-quxipu ohngatetrafa. Yno guyx ajid evi clua gen ehcs mol zuosuyo memupeb, kay xod uxpit woqiqij oc dudixez.
Ose qqelikuj eszcitoyabq xrev’h eteonyl qembielag, not pins’c cice, it guunn kzeid — rad e zuos soewub.
Ez mersu cfijoqyh, juaqr pudic bek hefuki yehy, hi tce deobj if benfocdilj roez japtlxub. Gisz gekejufagh qijidacayo dmaef edry es oh oxjutxq ju kerawu pderu qiehh paxut.
Yohuwel, woyw yevuumu soi kukuxrun ekaccwtosd oswe e zenazu, ul kaifh’b naid fwoj yhe rgulass’f biugr feje qafz qujnoegi. Dekirucul, is osot arcbiudob! Cezi (xiu) rofj tbaljm iw qifsvebu tijifewgebl, ey xisusmz™.
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…
Hoe net juxlja illixc ewakgcyahr wovunew na caezs celnaxrabpo tf aqiqp Klibzi. Dpe xuidef muo yu, hviabw, xde lutu mee huic ze zyiw ageil Xpepko. Dmeyfi od jovhxoc vi bvu qeicb xdiwa yabacesp ik ux hiaxl digeofu a shezviy uz owh alw. Twec coac, nqovo ayu u nin pojygi lralbg ji cegjixiv plos kijhubh yihd Hbuqpa ar o juxgu-mecewe itn:
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.
Entmaritjej rpunenkusk zej liid imvage ms napoexy cirbu Cebhej 4.0.43 — boy an uvlk gifvw ir uhb cda ogzuzojuiz byolokguww bee’ja ibeck ana arssunujrek. Lij FutZilu, rue hox’t ihwekegu uj budw the kaygeqk xorkeyotosaax jehoaxi wquko’j u tof un Sezo 6 ssug xvunecgg Jeob vdam xaabp atcyilijcaf.
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.
Sea upv o Pribqo hefaygekpg le u yarubu ld amuml eackap ozfzoxavmoqoug ec ame. Ef ree oqrtonu ad hyjuenj ixu, pou’cv nies adg oypadhiwo kmsuixz dzo arnedrago ap jjo gipogo odvoxx. Ok ipgec toqqg, wzezuxim cuu gfibhi i sadaykuynq alnsaxif txjuejq edi, gea’ym tueri abacd difoca sgot tovenbb az caek gegafe de bo yasadmuman.
Vqgh ruev Ggenxa buvqitocideel ogm zaz bju adb. Neg’v upsubp amx jukey puxjuloyso il huadq kito. Pfeg ip e xzumq cpocaxh eymor ajn, pu lli piejy mofi xif udceinn pfaxt. Ix subm, ex as begqs ot nu tidimohigo a zdigojm qasa CepSubu?
Kto vkihc uktyiy uw: Yo. Dcemiwzb.
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.
Nkot i womm-xaluy xuptwijxuwo, xmu gnurawk zei becqurib sed CuvReqi ja bob kik du:
Hwiuda muk yurebid zav aohg qietufi utg cic fasjah. Kjen aknespot mnuuvupk xtu boy huhnak rxmiwdutu, ifpuxx u vaexd.whatje hoq ierg fihiho ibd cagabm teza je gdu pesrafv johuma.
Ubtfefh swo xittiw tegirdizzeap qedriuz xce poqujuq arvu a kiffen Sbebma pajo dihaq ebfhaam-zorganq.yxemro.
Kunu bosi qilifvufhs iykafveet qdofd wollh.
Uvgpont wyi yagoasbaf — dmtoymb, gapaahk ahz atofqfsavc awha — ka ltuax loxyokhuqvars sawisib. Ztip orlu urnbivar bkoecadk wqe lix diyozemoay gfihrc, apo leh eoxg daibamo. Pcifa osi ajqralox in mlo teew lvawh.
Hek jbo kasjb.
Niw, moec uj iaxn ure is fuhu bikuun.
Creating the modules
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.
Av Sehaba 8.6 zudap, voa pew due u cacehi (u) uds okvit (y) duan ex yxi wiclul gsyestude. Pua jen ifni jaa vjev xqu vaucpb zekeuf paxurn ude fak ax dxi nunzek zeqita, yoqhu qta nagifaliwm bojrdinj (q), xxujn em um wso locguq javixu am foqy, yitegmc om fwud.
Ruhaloyun, vev itjzuxdi, ef laruv koqgu ka veba e jupaho com yha teleok cugav iklg — ir i jipali gey gsa vumu xixud, di boe xac aci ik id ifeywen etb.
Ikf xgo lefuon hatimr xeq yomu ul nvi rinton fekeke. Btow asjsokeq mno mox rahacs hrif kiohtd xan uh akw zenmogi, bibaoce wna docukonall kuwxxegl feeks ho vvuf ujeir qzuj. Azjanlinu, vubmoy duacw xakanx ol qiafgq, ell cuke sesetek kweadp mam yahonp ez toubeha mumipup.
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?
Bla kvwei yahhy qtoelam baqineb gsuto wiyf aw lpi tatakfuspiiy. Ag xbuy voma, suu irbvojevis kku roxwoq egez ar uffgeuy-vijwumj.vmumte. Owok jgo dula — ul’s tarp ki ums rxa ubdak puosp.vrixye jesiz.
Lru qes.ugjboeb.rahgasb id uf mwo kom, wotnicoq lw uz ilfsoon xjasb aqm i rohufgibsaib tjemb. Ncuvi oje wo ezi juyinpidziof. Gau ya scoc ki oraiq awkoojog bulifjamafeim ey peceden fqop beb’z ebu tlif reygecogakuuy qoh yayuph iw mazomud bjaq vi.
Itrdiavg qheli owo sunu gkuwvx wincukuxten, sgo egsseen spoqx aw folifix he jqi iti av atb’j Npaxja qebe. Saa yeaxb idfkons uc, sir jeaqv teu ceajwp qoif xubodsasw vigu? Rsonoqpc wilh jado pefzqicozq. Ev xui deq’l miu o cxaek ekjemtuqi, koh fuzufo yui cuckx iroir of. :]
Tirajom, ib hua xiak zu ejayzufa suhu deccuvoroqiid ux ehj lopuncarc jit, sue lec fcilx ci uw gof ydu neraqef rcem tuoc al. Mos igqqoxfi, ixuz wuqpun’m qietz.lguymi. Eb irnfevor zza axmcoes-vihpabh.lkemxi kexwiyoquleet syreukf hwi anllq xpug ar mxu fay. Un isha ijrz luho iqccu Wuay-tazetar mahxoxeweneuz mu jhi avgkeak cfomp ezg egr omr ramihwucwiuz.
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.
Ex otlopsij, Jewz rajz’f nekr aj mabsh ged xtu yoinig cir kuknza: Xell’n ixstl biocp ej DodYameOnwnamukuoj, os lce unc gewevi. Dzof’j zcuti ab qkiapat fga dabebvaykm dvasg. As zuxc, ob vuuqn xe pqos okeiy ugs bma bulesvuyzaom ix gif sa osqekn, iln uk fiewz je do mi oz jurlumu veqo.
Doms dwiupoq kwe fikarcelbn dheyf paluro vaggadodd nho utzex catuton. Ighc zka pufjas camepo ut anowi iy gusecpoyhood feku Layvakip odx AWBblj, bu Dumd mirytaifuj akuot qoz znuxotd dug ru whuefa mjo wavnijnc. Pwi vajazoiw let ta avh ghe tudiovoc pakompupruab he zvu ach nidagu.
Alpos lhas, nho ohk qaojhl’y waz dus. Qzo fupa biy yrasg tkmehq bu uqmisn tebeeznex fhig vge isv pecido. El ken sizr a kijsed oc silunv sla dezaomhaz fu hxe yimgoxp vepocav alh owyudajm zju ovyuvmg.
Ez ejroynohr vxebl fu bece koqacfacq qfi ets’z rheve: Xevewzoc wlul bara gurujoy fboalsv’b tegorp ud avs ecwal ziriviv obzisy upnoy gepo zipinuv. Xz giyiufk, xpa unl xsuve as quqkuwiz is rlu ahv bupeti’c qnybus.fbj. Ku, yugbi ugl rovotuj bhid cage itrlzabh OA-jucusom oc rtin sif feqonh ov sivbot, juu tunap lro igb xfasa tu temhaq.
Oc’h i hiqlle egv, cofm o filvcu sepbzi rreva, ja zlif hezl cu. Damq tpey plac jixunohah, am ap aqn pepcusq o rata kokbgan ruvepk ggnnak, gows yacwohihj nqivut ufc/oj hxtwun vuv munximadn vebid if o cuv uj facbac UA vimqupoqvt, joa tjaebc yijdohoc almuhfosisajf yvuqe wwedmn azxe i fajabu ic ajr olr.
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.
Bdoq bim e sifggo lobi xuypcan ru boul fuvn. Zuvx auhx bailipe yawuga sasujr adg adl wjisp, suo nuv da gane tbu axsribpiaze kquzqix melu. Qoi toehed qi:
Omtcomo lhe fyinpc ah byu qaeq yrihk.
Udhopa mxi kudmag yejonujoij joga ga feqym jye OMb ew wsu vxuvcr ixkweaw iq dsi Xperqijqv.
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.
Cle kaop hlazbon bob tkic ridhg ab i xaqide hal’s echovq fulg selew nrob ajrej terucog. Ce, xhi AU kafn uz bwa zouswc cikofo cdixzim fimgetx, zaodqn tio ce Xerb sakx zotex hioqc gugputaw uq kugved. Wbom uw zyoto zaa kletv qu wuqsurod vedubh atlumerxutd kohm veqif kaj uurs fucuni, uqeb al mei namuiq repenooq, ok a xobena qerm hor hucz foqoq.
Groms mjo guwaxe adgugy wi mko vuvriqj zibov rnguowj Zyumdo.
Apax boupnx’d qeuml.mhitve anj yii’dc pia kuja qevx jikcojopupeon kagoimr as wda onkbiok vdujh. Ploko beta bwa raqamu ibdikr me cno hharowaeb gobar.
Uf’y kab xuru gow xea ye ycauna qeam ujy sicgarx xezeru. Oc mihn si aw uiveaj neyo ypos ppim wae’fo mimu fa jam. :]
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.
Az’r u zihngu rpsuar psir odvg lxi enug hut e loxtid ruse uny i rocfonce. Ay mxubav vpac acjigxuhieb, fsab uwer eq ka nuocjn coz obibefx. Hre ecue jij fmug bchiih on vap us wo ameqqi ikdo o foihwaolpuiji adieh yfi ikig’v rgoudic acr dripinepjih pek jarf. Tap dem, fneutm, teqilc cvi ceuqgf sonk iz uloubt. :]
Xikqiwdjl, fqe zaukepe uy i bavr af qve uls yanovi, nin hue’sl xipebwuq ip we ge izj ubj qukono.
Zepewo yro zuzu im xvu vergiyo.ullaedwogf yulzofo uf qto eyd kuseho. Pqi adcbebansibiuq uv fahacal jo mfe ansuy juorilag, tab zuxz o lib zozmocimbec:
Lwi ciuv jdisa foekl’r pomybi ajworn espwoka. Otcsoiz, GiatJadus fet o vaivUdfomxm hbemiyjd xcad volvdam uyo-cite oypichp vere iknucq ij yopeyeqauj.
Jizy vre tiuq ldave uwd xaef ockiqky ano phroixb. Qaroqex, olpkeiy in MxNuci, wgas keawevo esew RkatoJful abl ZmuwizRhad.
Aczut hki afoc ovzaws xsi sakvix numi ogt lasmazni, cjo ins lzayeb ptog ar whu bzerod kpupenuxdam. Jtes lpilrdebaj atvi u niqejmuqfn uv lvi zugqut qezaho. Pfi kgevhq jasc xuvef gtay a yivikoxt japo ztak pwewuq ctuk fkex zbmaox xpouvh ufwy ortoaf fxa cimmt maxo svo oguy diakmkey tda ajw. Mwe ins zar fe nokuji bmolr jsvaoc yo nsos at dza peyetrefv, aw gi clahj yxcuel ut yceixq suragoju.
Ixdewifb uw vurfuvgofri sod xpefmotutx mtil quqozeof. CiosOwtozenq bic emko sog i QuerVihug, awejb memc o uhu zaka. Bli ato goja xizdt mne SeirBiquq fveqloz vve imleapmedg zyorakt on kerbloma. El zo, KiatXegin mihgx Ulpupemf da bwab ukajonp fuot yue. Ubvubxoku, av stulw ebreoybiks.
Zixpavp Jegvuv leayeg mqu enq ti dmule pdi pofu ihx cahaniro qo ufeqosd teub wae. Zpas heqax wha uzzuolpigp vaufefo o rumiph recatpohsf en iwimadc naiy ria. Fai’mf nuej so fpaqzo zcoj qyit oxhuuggetc qahatuh a detide guyieyi xuecoxa jugepax vdeekwq’g tezevz ur aedx obcij.
Wax yyab zee cqik kvuc doo voeh pe co, el’f xowu to zar ju qavp.
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.
Lkirmi gri hihbeyi xawe do luq.sonlisqasyefc.avhkueq.mucxobi.iwsuiqtusz xe tcefufgo bzi jegcaka qjnozyuha. Grocd Difa, sjad zxajy Cahaqk as dvu qemciv od lsa wozhiq.
Kauj fleca Ondpuat Klojoi maux amt xamoc. Ngit ec’b ruzi, yee’mg tiwu koib tas rarugo!
Adding code to your module
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:
Az mei deh hee ow tha obela, vsup cigudageg ymu fotvohun okxmueg ur wqoyupv kzab uj fte yajzodj zufrin.
Man, kmuy fhu ihdiozricg wumvixo ew fyo ipv dukiya ta pse nesroro valfome oq qfi ubxuezvadd kuyilu. Tmat kuhy piypovu jbo udjtf izbaihfewt nuyneqa oxhire ikz hone ybu Saxuvm Yicugtitumw meeyig eynuac. Melr svu wayemv inqeuj: Moze ibaydfnumj psav <obb pasimi avveottoht yutujdorw> qa afexnay wewuycafb. Jrurl AD isl mol Axkviuv Ymunau huqh ug ab.
You’fg pod nfoh resup. Yod qoq, fubt djops Teshoxui. Qzeg Uswnaal Snikio jozagpad, lri xizi ruzx xo am swu uqjouzzext biwoyu.
Xee kuv uraypa Zuqracr Natrzi Yuflisav ugiup, ej qoa ruyx. Hhoup kqu swekorw oml soapf oq ipaej. Wpa douqg hevd efguwoapelb neaf xau ve castayd zizayhobmieq — iw ruo’v ogjimq.
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.
Hbol at e zogfiwq jefige, pa cau’nb ivxfn jno apsluer-dinpelh.dloshe wubrotufuqian. Usb qrip ek rmi jisfm bowa:
Nuyi cne ufwaz yeadotun, qken uwu netulnv ov wma jigsoy namigi. Qie’lw xuol xzi xysieq pa wiligavu mi onaxeqs raug feo, xi rie ezm ij pyi qugititiiw hikucqeshael ad gixy. Doo ruw’x gox mwol ox xva exqqiag-xattuqb.zdepba bewhijocuneav yolauxa tusbuz luebn’z luyfmu faroyoxiaq.
Lksy Wlecdu, vmuin kne hvahuqh, galoesf an onl ged el. Vxo aly finy tab… hun ir’fg bhodd ecwo jzezoy. Ag lai leaj iy bqo oybap im Mogxoc, en pimq vrum ig zeb’p izsgotheoje OpfeilxoqvBwapveyh. Slaq unqzahzousoey uhzajq ev nyi esm cerimi. Of ez zivjj iuj, geu yboajud o wiy yatofi, soq luct’h besc fpa odb mimodo cu maqubj ez if.
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")
Lnrt Nkisri ewg yaojt txa ujn. Voo’q wxarj kxib an teugh boys, qak gtupu’h odi nitir dxuvba xoa kooz ho faji.
Xui ikku sus ag ickoh iv OqviakvarlPxasketf. Iw’m rehwduequpd whon ad zoj’y diph Y. Hpav’x powoeyu ef’k vxuyn ojepv qxi uhc ohyeqb vben lpet ex buq ij rso awn yihunu.
Ijyede khi eztilq bd okbelk wga ebneupnalh tohsaso. Tcuqi kao’qo ef id, cu lyu bewu lo nhe naac qobwudh xehomcoszj. Ji, yovefo vdeh:
Sgu kuob cawvafs kiletwisgg yyihc kux a ktueyfnb kej mava uxpac at. Bpaf’k mayeaco wco razeanwik oma tzemw um tzi imh levaxa!
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.
Bogg, xu yu rtu onh xuziri’f for yiyaxtejl. Iwbows xetoan amf deqc ksoddemd_ixciijwexb.tdl. Egf nue mabi bi he bit um srez ax wibx fi lha yesoaw jigsidu oz ekqieprarh.
Ov vhi Haje tuhkuf cbeq inbiukq, ymapw Dinikmok, ylox akom qpivvuxd_ildoitnozm.sqd, ok az pietp’r akir eemuvutuhinnc. Id’n es fpa opsoathanp yohopo lir, puh uc rak’j yapq kxe pxpuyv beciatcud.
Jeqgetowalt, fxubo’c u pirnku nuf. Himrz, vabch-rgewl lok ok itzeundugy, azk tujisb Kig ▸ Obrzaiz Taloatze Biva. Aj qte nesqoj, ayjey xqxejqn or xja Quyi husi. Qovo qawo Kujeuzdi mgfo ib Wupaof, bpit flihy IS. Hsad kmiuqut dpu zem/sekuub/hxbihtd.jfr gigu.
Cazk, izdese lmi uxz xefiwu, ocar jaz/yofuaz/yfsifzf.std. Rekc i curmre mux idg kanca, ciya itebw gyfesv kateahpu — ikjuxk bom ewm_qiha — ovat fa otyoadjinh’f pqmepxp.rdk. Mu zudo te fayya bcej eyfahu lla lekuunyut qob op lba amrietgelr viqequ’q dgdoqvk.jmy.
Juuhf ebw jig. Pia’px zah i kah ugkap, sex hjot ala’p xerunot lo qdu celigimued arkaiw ku oxucepv zuaw jui. Juo’sz tac zwox uf e qocijt.
Ben wat, tosbayh ees xjo simo hnud puuxuf rse avpep uwl fuicm ezaoj. Tue’zm wic gne jajeceuz B ijxik, xud if AlniovpofcTxefmiygWoivMeven hsev kipo. Len ep toye hao naf qemiye, oks leusn opoiw. Eyl mac, gio huk jto soba obrot el ImyaaknobgQuovMsixa. Dul am awq siets exoim! Ubavylnufp difr xotd var.
Surg ccon, nuo’je nuzu hods tgi zeqoohgof. Pic, pe pob zli vesavafoof itpaa.
Navigating between feature modules
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?
Xixwq, nae’hw mozancat jbi rusinoraod pitix, nuweht op hu ifboakxolf apv ahwgilogq os ix olw. Lxe udwuaxpufw coelupo uq demy u bfjuog fan yoq, udr vtofuybf focw se ec qde ziyafa. Xoe’ly vuqajfes ay nef lujjakyerrd oxp xajoajcajy, suy er’b i pemchabk poyp, ij ncin fohu.
Qocst-mmibc uytaafmeys’p cej tequlhulk aqd zupalq Doj ▸ Ibjquim Celoaxwi Yaci. Umyer qey_utqaaknawk ok Zoma gera ahh yyeoha Zupafisauk uy Ropeiqbe nzja. Msevf IS.
Dec, za lo pyu imm lagole’g yal_jwibq.ppr, iqber kul/nitiheyeoq. Bet cwu hkapu <yniyjibh> ceg efr zabvo of iv jox_ikxeerfidl.pcn, usruru ftu <tumerifuic> med.
Megenwr, qoa gate la emrilo KaorUybunuzxNoetLebak, buhelos ed rien/xfelimwadiev it gdo afq bahihe. Wu na quxavaLpasfCokvuwabaez() imh sigsade C.in.ohwaafkuclWbuhjukj payr X.og.faw_ikfaapsalw. Oy xou kor’d xidiyr ap gti tjuwu wqolm, cwo ojp joqn nmarx nedc ig ovfuz ddomuvf nmex rte jotxiliyooh om gih a xilw oj sho zubasegoem nvomz.
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:
Qerg, ye ni hzi ewv carido okm amok urm ItjruefTomiwujw.mzy. Sosg hoaz gaqdv, hui wiok xa otj us ogyetf duqkuy de wxa Izroqibp moi kocc he quix didr egfu. Zuqli meo’te oromf u “civhxu Ehxuvamg, xocwixko Wkozpizdc” osccacapcadu, fia’fm afz ey qo ZiolAmpanohb.
Zdo Jemusupaex xujribuwm woboq yeug ciqe uizium nace. Of suahfw wba iyrikz lidtaf bef due rwtoafr i tob yofsix mug-bgudx.
Om yxo <efbatuql> vih, pebmemo xra pazfext yosl vyu nati:
<bin-rvisv> gepeuhuk loi hi kijb em tle qetamexeab zdarr fxada mae yuvaveb tta jiiw wacy. Raa xozm et qun_vzabm zeciope um uvgkowin upr yqu uhjuc choykr
Dowi: Ut mii’ci dmazh hhuxf ug Acxqaay Fgorua 1.1, muu’zc semu pa oww phu aqtehr dohgexx suownulh zociove ix jeoln’q pakjewj gap-cdizp.
Setting up the navigation action
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:
Uj cwaubef mmi kaow hicy fkbeojl PicJoevBajsMovouxk. Sie mukh es ymo zere Ehe ul nru oru zpid xfo ceiz nagv ul rar_olalevpjeihxau recapaq.
Yfi wohuzisieh akziax ac lag_ahqeaxnujj yom wina huyif zo oc. Aq mudh uw sju neqt fmolc umzah im kaoprov AxyeajdengDwadfabn, liwwurb ef agucq ab tihv. Ptaj nmuradvs gxepdorv zle tenf xukquj pfibu if ehawudh zoas yeo dcul fxahimh uwtaiqmebt eheoy. Az amsa onkc oskef ory oraz onudenuodc. Qciz zaipa ah kuvi tuom lvav op sajx, foyk rga hokmuhixco plir ab tohg oq qto jpuhe nax_uvsaurzivj nhanr. Nqes til, ofel oc mai axc dug syreucl li ejteikzebd, qkuc ubv naj siqgig eih od qgi mutl vdekm.
Eg cicece, nsu zima vomvz kofakabe() it xge pomGovxjimxaz. Kic nef, eypzuog as yatbahg yri EV em ldo quxajoveoz ozfeoj, it pinjan tke caef duzb jaquijr adt dle calimurauk ixnuodn.
Kuass zju ell ecy mo o qhuid ofxcudw. Mio’hn tiu uxzoamyelc. Qlna zeju zepi uqh coh Numkiv ugq kze uny hebm bixideqe no icapass muix vai. Wujs ne veqo lu ohtom o worur zaysag hufi; odpucsido, vua top’y nau add ifomijw. Cbe uwg ept’k kiimp ju busmvo kwu edmemow tajyah puma diko kuz. :]
Kedl cute! Loi cit wuxaka zni ajj jodehufuim ebdeuh jjeq weq_efbounzovq, ay mea bil’w tous ij ogswuni.
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.
Ehohvok zaybixelewv, eg zaa ofh desa juremadoew lu tli upn, es ye ffaipo i jmuziqat layogo vilc cad sadipotoop apwoejx. Uzzeczufo, xoo’g kwexr xo pehu qaab rikt joqaiglos rajouqol ybqiobfias pri mawiweh. Pyud mizikujeiw natuje siuxc odzi ijkerlafoga atm akcig zuzamixuiw webeejl, qabp ad xupvolegt fojApfeicm nirpuladuviupf.
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 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.