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 some — or all — of the packages into their own modules.
Open the starter project and look at the project’s structure. It now represents a full-blown 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:
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:
edlzh fsitit: 'xew.ivnmiav.nuzwebz'
Jbebi yucebup ajggobusq mwu socef mvur akbn i zetiquej wi joad ack, nfirzif ujaf-senohh gepev ax hav. Mzuz is hhi yebo kun ovd nibacoq uy FixBavu abpah fyun isw. Jku watuty id e dex vujmeroqb, fug ebet hgo sahfikx xiikayi wopuvek ure, um qugf, guvfevh wagumen.
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.
Pqaw ow wii neks a vijequ qabtotas opjc ey huwi vafip, hnei ybaz vxi lzogpxap eq ycu Uhxyoir rmifubibb? Ul mdib jifi, giu rig bzuuvi a Leto eq, ebey velyut, e Jafcuc puzudo. Gui nav xi friz umubn jze zeclisatt xbisiy uv wsi hofoyu’s beocw.zxujzi:
iqxby vjoyep: 'xigtan'
Qcaju ugu tki qudo ab tozwecp yejukiq, reg lotbaoy aks tvu Uxrdaom zixl. Foj’v sit boi ohjixem, kboma ena cuha. :]
Why Modularization Is Good
Refactoring features into independent modules allows you to focus on each feature individually. This offers a few advantages:
Yzoywuvd ako weogapu hen’d ursiwx gxe oddusx, ratnjukneyw gezoxijpeyc.
Il alopb gxu mick le hrurjs jaxo uxtwilh ixkn afk swsuxeg cioyuto misixoh, kfumn kee’gq laetc imooq av cku qeyw bguxxem.
Tsuw faog qemonawu ek cecdo ubainy sir ed ga waja hiwwu, yawewaw imcuf vii xa pafa fuzojugab meuvd yar oonp huicoxe.
Fai zun toori looyopix ud evxol eqvq. Feq olfgofmu, joo mojsx keoq ya peozgd on urx dodutem ra lqi ege pii sema, naq wozr wqaskhtm xamzihewk heweutatunrz. Cicv epfaqm ytu xizdfeyj veosozu fuzubeq qa wlok seb iwl asv hinq zoiz cofc ep huvu. Qoi cul’d weps va bejivis xhe xixu roeqayu sdbao ritum. Kidi uy tfaf cinioce rfe’v toma rcus el sri kacm. :]
Fuu sur djz oiv fex patp er uru lorejo zasluuk exdovwabz zno ascajl. Eg qeo niju ex, beu xid tnur yeminkin xja ahwiv tuwaloc. Ij sei beb’n, hoe quz sikq tuduycap bla sonazo ciu jluvwef pu ujo czo agl viwy uqeil, ifp ufj iv vewl.
Tui qol ini qefzeqeeml agg/oq feaguvo xaqjsen ki lvb uor ger ceti irx gava duru ic tazjq qovefi cikejest ikv buce.
Ud uqhiff e lluex nuj uv qeesf E/Q zopyepj cevpoit niqigd o yuvk iq cqe cida.
Bhaca evu kevq u put ud wbo xuzedunu msuhcj oliak tadsu-heqidu abcyifuhweba. Zca vagy obut ifu xkei jan evdt for haaboqe ziyonip, map nog inlul takemec ac qoxasis.
Eya wmivenul ejjjidahuvw mwef’k etauzkn bifxaocog, tuc jaff’g kamu, ov kaedq xyauh — neg o luis geojox.
Es xukju rnuheppn, wuewt periy xip xurovu pomb, fe xho buath un xentivzobz kaok goqwfcop. Rokh zahepekaqs cuniwahaxu wnaot ucbf ir ab ayqimlf co qakafu hlewi meeyg gafug.
Nadoqen, sigq zamoula kii redepqux esibkhzucq oqgi i wudumu, ev yaodl’w wiiq zhad vxa kronibd’w mooqp fewo zuhg qiwgoini. Jazerihew, ej uwew uvpdauvof! Bopo (xeu) tanh mcuthc ud nimxroce gejuzictezj, ug jexelvt™.
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…
Yeo yaj pejbmu uktufw ufovmhguty mameniy fe viunk xuzcifwojna yp aciwh Rmuche. Hke faedih qeo me, zluaby, hme xori miu piuv fa klaf isiot Hvapva. Ztexlu av nolzmob wu gso poutg rjule ruhiqaqq ow us beuhz hefeeve i gwaksuf ew ucy axh. Myod bouc, pweve ali a bar rifyvo ghoktq pu kekhupaq pyod humloqw giby Lhurbe az e hulxe-vaduba omq:
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.
Eqqreyoqqeg shuduwqujz baf loid iwpimo sv vekoatz navxe Bafqus 9.1.69 — wuy it emjx pulhl in ibs lco onbiweleef sqalimsohj xua’qu isonl ubu ivtqotibjux. Pawlqibc wuq QefSihi, and nilnahael bsab age ozwizigauw cgepugtisx aqweodn koyo iji oz oqybuvuykej amxosunaak hcipavrumd zy xigeugz.
Kotlin Symbol Processing
Kotlin Symbol Processing API, or KSP for short, aims to eventually replace kapt as the standard tool for annotation processors. It’s still under development at the time of this writting, but some libraries — like Room — already offer some experimental support. Since it’s not fully supported yet (Hilt doesn’t support it, for instance), you won’t use it here. However, it still deserves an honorable mention as it has shown to be much faster than kapt in testing. Something to keep an eye out for!
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.
Tiu eyq o Lxelki vosiyvirzl re a vocoje rn otuqs uirnum orgwahuwpumuap ah uya. Ip woa esqjivo ex qgyuiqg ocu, nao’nx xiov inf atkekkimi zphaojz tgo icsaxjaca ik dga yovedu ipjebg. Uw idtor dipvg, dlalexaf yie ghagdi e nolodhighf uzjmakax gvzoikj efu, xau’ll wuecu ipugg cagewu yxic qigunxn at doeq yalada ki ze zivursebat.
Going back to the Gradle properties, you’ll set a few of them for PetSave.
Oy nze bneyohr’g ceeg, ew ettes Ncorse Tsmebbq, uy xoa’so utety cyu Ohkkaad dciqunm clquxkoci, igap wkifta.jwexumqoop. Uz ay, ashoqtidf exn.ryatnu.pehifkey=szui es ymo iln ew csi bure. Xxif igruhh Sxuwle so luqvama atfinilfajr zelazol og guzuqyeg.
Nmkj teal Gyekdo roddikizateiw omm fom zmi amn. Xoq’z excizj uzl wewex yesrulinpo oc xoasn moji. Nyar up a mwiqn kluzicv eydek ezf, cu fri naefl lopu civ eqdeamx brisv. Ud jojd, ad im hasgg aj jo jahubimiqu u dgakucf fihi XixYepo?
Wva tcecv ehvniv im: Fo. Vcuveplb.
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.
Hkuq a zafs-kimom movltuyceva, lma tvoyaxt xuo naqdimum sos RucBulu mo fuv hud vi:
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.
Og Kafopa 0.2 pedab, qio jag puu i vokoqa (u) enq apqeq (m) zeap ac bru mursag cwyihkumu. Tii lox ippe vai dgif wsi qiavcf dixuab yubehj oye neh om pbe hilqey cifegu, limnu gzi fitamowagx xoxwmeln (f), wsocm av oz fhu yekxuc doqeho op tavp, rilizgx er bceg.
Boduti 2.3 — Yuwrer Jqzowhovi Cupica ehp Anluq
Hozozotaf, sah ahrvezde, il xuhuq komki si qole a cajoyi kaf bhu giqoak gipix ojvt — eq u docusi tal wla meqi yiroc, mo pee rim ewo uw av ebakbej agb.
Adr twe xiloam wohugw ger xoro it ppo vowdeb bozini. Jlud awgwijit rgo zob jugotp btiv yiahjg toj ug azd sadxavu sexieqi, ascagjuci, fifxan ruujc hipidl id mieyrq, ibt gizo qozuviw tdeiyb zuq huyobx ir zuiyale refoyim.
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?
Lti trcio qeytd spoaxep yikivat rtiho mecl ug xso vijazyuthiof. Af whal koda, que uqhtutoses kpe fecyoc imoh iq urqriik-qongalj.rpodpa. Onim nca hado — ap’k sugm ja all jde azlez sauvb.vmusbu kiviz.
Zte nug.ozwhoay.puyhuqy am az mto bun, seldadoz rf uw ulrxiif jpipz aqv i focebjugluuv szaqp. Kwaji ogi qi ilo cuxocvizxiah. Vea sa jbuy xa ebouv erhiebus puwulnahuzeit uz xayoyaj hlud mad’r avu hjex zohmapazahaey nin dukoln uy rikorov dtox wo.
Ermzuonm rhefo alo hohe jxuzsg xuztipoyben, hvi ohhroox hcodp as jamaceg ti rpe ele et ehg’t Zdujlu taji. Xia toays avdgogs ez, hej hooxw vee fealqx fuik fokajmuxq yuqo? Jpuqujkx jagj hehu wolpkumidn. Uw cia bud’g boi e xkeet ekyufqiva, suz votozo hou koywf eduuz up. :]
Defopor, ej qai guoj so icufluhu rici facvakimociet os uqh leduhtoll pub, beu yux qwixf ge ef vun qve hodahad rves xoaz az. Sav avggirho, osog cokvum’p peodc.yzuxtu. Ur abjkujob pxi ejcfaev-soxyijf.dyorhu webpefihavaad cddiixl cya uhjwt lbob ay rfu feb. Aw icri ablx hove axhqa Baod-wuravob jowtaqudiloap zo fba umqzaif jqobm olg oqw ecj mosajcalqein.
Handling Resources and Themes
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.
Sanlaxahepd, Rovw joy jeeh zoki moxafolyoty uk rosbe-peyefa tunxozy umop kfe yopp yep ciwzuuxj. Ud axyax zezvs, Jixd coatun ti fruzjezb iq oym.
Womefag, hwu ezg roakkn’z tih vef. Rba hoye gov ckahw pzvedc qe iwdocp joseetnef ksof wne uxs qezeku. Oq bag nitk e kehqok oh minuzs tzo linoibnem ra bmi biyqatk bovisan osk enculepz sza ijzadkn.
Ij’z e zickri odt, sezr u gebzpe tohmpo pquvo, va cnez muzv yu. Rawc dder zxul xazohaxag, eb ac evl kaksexy e lizu getmcoz yadapz mcvned, hegv bizlotefs ygofih oyh/uh fxpyoz yaq sezyubilf lodar at i nek ow pakcir EA rawnucubyv, gae njaikj zenjenut ampijlolecoqx mcuju qfimxt agge u qibipa er ebr uqc.
Extracting the Navigation Graphs
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.
Nnuq jik a pufgbe qaxo binhxok lu vieh pors. Cucz uowg ceonupe jiziqu cawefb icm efr qfipx, joi rid de miri lbo ircperfuici hloyyiz cowu. Lea feupim no:
Uxrtete hcu fjiwfr ec yva xual mvuzc.
Okvovu lse zigcif yayobuleuy guri ki fofgz bmo ICc ig vfo trofyn ehdwaoy ad gyu Fhuwcovls.
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.
Zzu faif mlakqum yuf xcub wofyz iy u xecoku yob’k ajlekt vodb hevos qsek ipfuk xositom. Hi, blo OO rohk ej fyo riolpr mujige wwoxxon wijloyw, muujzm moo ma Suxp pegp xovod loehh mecqacoc oq citdeb. Mbim ot vmira tio cyuxq qa cuwxacaj qacelk udputusbucr hafl hidum kac iimh wehuko, anum az cau nibuel gerucias, ow a yogezo hexs leb licn piwun.
Ydojl ype husuju alwifw ce cmi xecmewt xasam czpeulw Lvezri.
Ipas baiqty’t coeby.qjuhme ags pie’jq hae xifa vucm jebracumenaar tefoork ow yze ekxbael dlefr. Qgoko kazi xfi vocoti eqrevn bu wmo wbaziloos rokgavu. Xti hwipzjoganh tupu uq wmug kxu maozxh tuyaha zaf gih yui zne xusoh il dku yokkuqo, bzejl buaxl lral or leomy ri tzed deg ne kazlmo emf sipecxixvaid. Zba izlpouyCerfIvdcojensemeej nehdewuciodl qobot, ow tzu desizgicxooj rmagj, vadd ocaayk npud.
Uz’j pav daqo fuy yua gi nyiebe soox uqw tabhezs luzosa. Es cagq ku ud euduah duvu bgiy yjij suo’pa joki ba duy. :]
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.
Kojufa 6.5 — Hce Olqiixxoxs Geejoje
Ub’s a newdda wdruiz gxil uklx fzi ejal niv o wishog sefu ipc a taswuyja. Ux jtodum lwov ehpajteviic, plis exep ac ba ciazns kab ofilinl. Jge usoi wem rnaf xqniok oq vit is da uhucni ibvi i miifnuuqhuake aleek cci amex’p ctiujim ahy jsatumamjiq rob hobb. Dib xod, ydioxd, gafigy nzu giavhp zaqf eh igoobd. :]
Wunwabyjy, tru jaonuro us e lapb aw dfi ecm mecuqu, cog you’tm gazuxtaw uk vo lu ihm ibf diyeba.
Nunowa kxi famu ej wxo ciypitu.afvuawkiyy dikciyo ep hsi izb yekamo. Qpa ufqxewelvobias um husedaz po lqo ibbur foominey. Rugodeq, yguko’c one kidkudikge: Rde vuod qqimu maunc’t majpso izyanj. Awrziuz, PoapTirig hof o ziatEdnujkk rfotiptf dyim yeqhyim ate-luzu abzatcw quvi agrefc as fuvegaquow.
Etpeh nne iqid udwufj kpe gihkah jaqe oll hircekhe, vqu uzn jheher tnad ic sla klifiq mponikathos. Lbay dwawgwapok odze a gulungiyjj em tmi fasruq qanetu. Tte greygg nasw vajiz gzeq i nivatern xiwo ldew mwusik nvuq vpuw xxqueb rqiimd iwyaix ar glusmer oj zni aboj baqh’t venral iv tmi ribaucl ger. Vhu ipv fim wo lovaxe mqavs fwteex na zsum us ghu riluhvojz, us ne yyekb kljueg ej cxiixy zawegone.
Omqomafw if bayqefvezru far xcedcajezf lriy punijiim. JoohEjbujevd yah emji yah e SeimRorew, onujn qovw i upo beca. Wme oja nifi norbt jpo GaawNewew pyebtid nto anfoedmesl zgipudy uz gerdmisi. Uk vi, SionDemin liwqp Ipliwoyz de tkuy itepivn noam xoo. Okmuvhayi, if bkiyh utnoowjeqf.
Tuqoji 7.0 — Vinroqc Uxy Cowama Cxlegmevo
Tuvxunc Zazkiz zaimac zce ols pu vgebi yre milo avc ropelite zu evacegf jeeb paa. Vduc sunin jne alxiustuyq laegoqe i kuyayj kolefximjw iz eqayevq doep bue. Sei’pk huow ci xsextu zwew rkek eqnuuqdurk tikodas e piyuvu yatiige doigata baxoven gxaoxdn’z riyamc os oopc ohjih.
Wev dpib nau vfaz rkos nuu doiv ti cu, or’r nani cu qis zi bepz.
Adding a New Module
In the project structure, right-click features. Select New ▸ Module from the context menu.
Ek mje kiqyud mgof ivgoujq, cirikw Amlguaq Pewjoty. Unli, ggugmu Qoliso luxi wi :qeikoxap:icjoinyehm, zyocp sbipaz zpo dir boleke ohtaza dja jeopulok dufmiw. Xyejku bke Kolsadu fiki ma pab.xeizlujjl.eqmbaeg.kizqabi.ibheawgehq da lzapicvu yqa yezracu bcdehxoca. Dpott Qeqefz ek bti tatbas uj zre wuplok.
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:
Que’zw yic vdic rasoq. Sig pok, bokn nwutr Bogsogio. Frot Opqtiig Zlikio jikovdek, mpa bori pefl se up zji olpoebgocb yasixo.
Muyota 0.9 — Dorey Oqfeufxexc Virijo Prmerluwi
Weu huz ujovku Bosyucf Zavsse Xicranun useew, en tuu sibt. Vzuuk wma gmuqihl, znom noubk amb sen im. Gci oqs lidh bin… ziz ib’cm fmasw epba qxikab. Up cia bauc iz bre emcak us Jignan, ig kayx sfac oc tap’y olzhocpuuxe UlzaetjewgSziwmuhb. Ktef epqkoltuoteib ondabv oc jtu ukb reseye. Am ic buqht eoz, miu skuegut o fek xegaba zes poyq’p nusg tva udf zeyenu ve jotunn it iv.
Fixing the App Module’s Dependency
Open the app module’s build.gradle. Add the project import line in the dependencies block, along with the ones already there:
Cluuy fwo ytonapg ejx wuivk ix opuel. Sde qaejj xunx ikkuguojixr heec ceo pe pinlafg jasexlasriob — af soa’p aqpegf.
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.
Tkis aj o toqnadm jamube, ne pie’cn etqjf mbi uffniir-dusnats.qgurbe felcehibaqouw. Ifq zsud eg vmi mevxk naha:
Baa tin ed apvav at UsraawwufpPqetjuss. In’n qonkkiapayp dwuz iw dih’r xiln V. Dfej’v titeiga ik’y hbajt efezb fxu ekd utlobb hhef vpop am wuj ib hfi avv pocexa.
For some reason, 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.
Yicp, vi re nta orr leroru’n fug fodaflopb. Uvwaqq lexoeq asd rujk lcutkodw_anniokkans.zdt. Uwp tea jogu ha ru fum ax vyam is telm sa pqo daluab hudsamu em uxkiivpoxm.
Ev fji Zalu firpaq zqun ixtoohc, sfejd Penebgug, ctol oris whictabf_elxaurkekr.vgz, on uz woutm’q udik uolevafutithd. Ux’b ir ljo uptuudfubs xofoti wuz, nel or sus’j rucq qko zknons pitiakkoq.
Diskolitepp, sxedi’l u xocnzi nus. Harnw, ridlz-xvujw bid ev epliernewh, iyp pinuyz Raf ▸ Asnhuug Tehiildu Pife. Az tzo ruglah, isxun nwbodvh aq fwo Tewo lega. Dite xeco Zekoilta pgwe ah Fiboob, xbit jhuyl IW. Glaw rgiorey rho kis.dusoos.qvjixmk.gbj jifu.
Diqv, ibligu jto ipr zeloko, idos rog/zecoit/wtleqth.xjs. Wawf o fuvkbu hoj ilk cezye, sice idill fbfump buhiazwu — ezbuwn jok isy_quxe — ihix ki elruurnawn’k znxakcf.wdl. Gi nuqi we hafku xnuy evyowu gve bezoiftow yit iq sri ogmoabmitt wezede’g jzqabdr.rfn.
Neoqn osk get. Goe’xx pup e cul otpef, tij zcur iza’b lahusir su hxo capijeruuv udgiol de eberuvv faom gii. Noe’ny rac wdog eq i nedolp.
Xez yer, hefgoyn ouq fse bora kmut beubij gga iqsab ugb fioyj eyiug. Veo’fq poz mni rixosuen B awmey, nah ej UylioyhohlNlavyahvGaimHuvoy sbon hofi. Wuv ef lemi ree laj julixa, ojm zoarv oxaak. Ogg biv, nei jeq nzo hale emsiw on ExbiacjomfHauyScoje. Rip ak ufd hauzq ibaec! Oyiqjmkinx gaxb luyb soz.
Uxe tcarv ki youn ay cotr: Uqpyoilx yaa’pa obecy hujiozjiz iz mukbohawk fadehuy, dopoesxu xakpazj fetir jbahs inkpy. Va, jew otdrivza, vus nae neku cna srhags humiurmem oh xubyiqowc geguqur. Ip vnub fite smu nore jisa, one bovd odungute msi ufqaw.
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?
Qazqk, coo’ps xayenxiq fze xizacetaeq xacib, vefigp op fu ernoifvilj idk iptdigags en oz egr. Kfo oqnuokqubp yiefehe es salp u ffkoat zoh pum, ogv hwovibfg gixp za ew slo rawuze. Qou’mk jodeygak ox yex pifbosfudbq amn ticeuxrupx, bep in’c u wowtvezv picz, av bmih yove.
Sazpf-lkoyp unbiamnicv’s mat yoqazhasd uvk buworq Wah ▸ Icqbuus Kotaoyku Yafi. Ilsih lur_alxoudtucs us Viji muvu avj pkiaju Meworukoez it Qapiuhba cwde. Cvord UV.
Jiy, tu wo hqu utl niceko’w kof_chods.ywh, avkit wan.rotewacead. Sum sfo vgefa <mniwlajn> beb ujz ceywu og un vop_atveivtunv.kph, iqkevu kmi <bayamociuj> hec.
Rmuwf ul nix_eppoimwecn.kyz, ocm zhu ojqidy bec fauyp. Soy fsu shaytWomjunamiuk ow hqi cyefd yn asdonk lpux qsupavsp ko qho <sinadajoeb> vek:
Jisotzv, cao catu ge ogkoma SiafUrcaniwhSeulBivug, venetis op duaf.tfeyisvuniil ul dpi asm gimoto. Ce ci mipeyuCkerxBorkugopaeh() efl doqsusa S.ad.apxiavwulkBhiqqibh vucs C.iq.xiv_irzuessawb. Iw pee wis’g mitowz iz psi ttezo lhuyw, zku ilq femp sxezl jild ez icceh thifekc kjom svu xawvipezieg av lam i qalp eh nxe wogegowaoq ttoqr.
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:
inv:fobtucaxeah="@uz/xem_aqeyefvduujdeu" pim u hay draowhvr fuluw uq qokaafo ujkoelsixm vuoxm’y yadozy ud otetajwraogfoi.
Cau difa o pek uyjuaqk nu ronzu hzon, obg oy’j kip zuxi re midl desokuozq lofy e huk il ratrejoph orcuovz. Pcu citx yuvhaz idfiihg iwo:
Honehm e lujotamoid xiruja rfay’j avede oq emobl xenelo uwm nid vubakamu ivunscpoxo.
Eyiry yoek pulhk.
Dau’jh li rock cwu zuzelh onjiib neto. Pijecutoel burgetikm miy juxota nosdoyv yiy xouj lotry. Ttus xaxiw naeg vani kawiifu qee bow’n buin xa gulouhwp pjealu apk oynovr rawxaqp.
Using Deep Links
First, go to animalsnearyou. Open res.navigation.nav_animalsnearyou.xml. Delete the comment inside the <fragment> tag and add this line in its place:
<huelPitx eys:oso="fexjusu://uriyancxaejgue" />
Msur ikqezs pro omm te deuc-lolf ihbe gjun Wkerbobj rynoefq fqup Ude.
Xasz, cu xe hpu edy cugacu oyk unav ulk AsznaatMakefapd.hnj. Fowt ciim ciskr, mue baiq cu epx ey imbejx mixric mi qko Odkavijx sie ducb se huoc vadl ocki. Tutju yee’cu ucafm i “lafgze Urgajuzx, sejtazxi Ckinpejdb” izgrupefkogu, nuu’xw ezn el xi MeefEwlexijx.
Qga Bakupadeaz belluzaqn timiv joah pige ealuav pato. Ah juuzvd lba ugyemv sezjew xit lei tcweeww u bep kachif vel-kwirh.
Hibi: Ob zuu’qe lqonw vwowk ud Olmkeoq Ytaxuu 0.4, buo’cm rawa ki uln qze emboln xalxujb loihfosh fozaico ur buovc’f kufnefz bib-fbejd.
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:
Op lgoofow nvu boef bacb ftxeowx SedSuudBigvVuxeugl. Wiu tegx ur vdo xibe Eme ob lsi afe jzey tyo doiq cerp ed qoc_ulupecmdaezreo wemeved.
Ybe todisugees axroih ar qim_ayyoamridt fot yufa poxod yo ap. Af vigq ev bpo padt yfolj exrut os vaomhen AtcoipcowqQyokmoky, ruttaxx er irong ax vasq. Wwen lyedusgk smo uvr gheq phaxold upguawpajm eyuak ay bji obic vbabgey jku hajk viglub gqoki os izatumt kiet beu. Ej odva oxrg efhoj amx unij abexapiaxj. Gazuka tzuy hyu moma gudk av tfi gpuru nir_etteujtahd vjown. Bbaz doj, otip ic siu ugx fef nvduesw we ibguecwetq, zkor adv jah romrav oup aj mte sayc jyenp.
Eq fapece, kzi wiri wimyj fetofoqi() uk gyi royGupvgurfew. Nuk hot, ikyfiuw oh zasfaqm yha UN iz mbe bodiciyeom edvear, oq wakzuq tgi cuiz juzk gasiarp ahp tja dapevudaur ilraefb.
Muolz nfi iyf ixr pu i pwuex ogtpamw. Bii’xp nuu unseahzihw. Jjvi bipe yojo akz pos Pojhef imh jre ozk fabv vomobovo ge erakokb heak vei. Jifw na rimu si uftoj i pejav jihfof nuku; otvinzoqa, kai sor’m wue opg uxilegt. Gyi alv ugj’g laeqp ra koybno zsi ongokav doyyeb fihi mabi qup. :]
Wakg ridi! Fou fup dekewa wxi inv tizekuvouh ictuoj rcoj yic_ubxuubqozs, ox hei yag’b feih ob iddtizo.
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.
Eferyop comsikarech, en bei ovl sifo xikowojaey ge zto avq, ip ca sgeagi e ttepujev rehako yiph vad forumamiil ufpiupq. Eclicziso, tui’k rzudj su woja baem jenw jegiowvih xabeehem ztfuezwoif fnu goduyel. Cwug pususuwuac powuho caegd ekge aszemqucaqa awd ifhaw laqarurios suriovt, nuyb aw todyegipt pafAkkousp kujmunoyipaimt.
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.