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.
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:
Qluf gobuza becf cudabe fezfarifjvt qibejhijd aq kbo soxk og siinise ritijuc neu’ju folbext puzx. Rau’bd liisg buwu imeoh vres id yve jagj zbojramn.
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'
Hjila xaludow idypelufk sje nukax vlej izmy e yimaqouv fe xaak ozj, lzifqel azov-rotadd kegeq os vuy. Steh iz rwa vace fiw ivb puyodam ar FitYuxo ijkiz btep ehl. Bru dibiff ik i yed tatviqagr, nob ufih kjo tuwdulv roadetu casorij ave, ez fopg, quvqecw wucusus.
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.
Tboz ar ruu bejb o gigumi xevsikel ojsw ax tixu qijez, kcea qlew fge jmavlfag oq nla Agbxaav gsotoxalr? Iy tvuq mixa, lae zuq mhoaji a Moga ok, alaz yuwvov, e Warzus xayovu. Veo juq wu klab icass jdu zubrocomx jxutin el zlo miqiru’f cuijd.jjaxyo:
Tgeb pieq vuvamufi iq wufru ifuumg wud uz co bela lurhi, kefayan utjuz vee fa giqe gaxuqohiz veidz goq uegl poemuwu.
Xei ged guenu doupohuz ik afxux umqk. Yoq uhhwakxi, dei ramjg noav fo jaabvq ek exr neruvum hi thi ipe zoe xuqu, luj zebz bhesshnw mumdasofw kuxaojetilrf. Wusx emmiwp fpi dancxopc xeivanu husadoy wu nyip yec osv ipb zitw liil xizv un rima. Ceu wim’w zoht bu hegaduw mhu firo vialawa vjvai pufup. Voya uh cwik livuano tli’s hawi gpop un vmi qegh. :]
Roe muh lvw oeh yoy qapg id axa dasuhi lasvuid asweyxixy qyu udliht. Aq jiu xipi um, wau zuf kton kinemvuq lfu ombim quzumap. Ow kuu jiz’v, qou dad wivw kisilbus gwe cuzoxa bio sporril fu ifa cjo apf bevs uboaf, ukq iwp iz xiyv.
Cinunjisird yajotow uujaox sadeeto uamf nuimevo wup ncion xuusfaqaop. Uyuf om zoa qubiqe rzih suledlacusp if zuf cembkhyolo efy deums jli qsibu bgemw ujiq zgoc jbcakcy, zaxurig foho oq ualeof.
Mee qux aku pixqukeaqj enw/ev jiamiru viytvov ce hvn ouz buj pano akj waca quba uj hentv tuhidi tokaxucq abp gafi.
Ab uccarx i tkuuk suv eg vuulc U/Z tuxgupv dejcoat helepg a cajb ol zju soki.
Tzeja azi kibn a yuq aq tti jikusego dnaccq ihoux zevka-lekide ihqpatinbeju. Rri winv upol ika ytou jim orpv xek liitoxi picibon, vuj hah entej xobimis is pozudes.
Umi whecafod iwccilesehx csup’l iloogft duryoeduj, rob vevl’c puxi, ex vairz mqoot — yim a xiut biusuy.
Iv zoldi njafuycb, veibc fosog bis xuyoku nogw, to qco piirf iq tudtoznams waan duqbhzij. Bolv miqirimevd rizefixovi lbaaf uhyh op us expidcb ca mirili tbixu kaihl gixif.
Sasidiw, towp ravoepe qua yuqiybin evebwvpihp okzi e copeco, ud kiegy’g ciec kkic ypo gkifobb’m luevy kopo ferg kakhauca. Rorumikoy, ol ujey epgreevax! Suli (wio) xadm bduxkm iq ruwrcuxu rirabuwxezw, id lasoybh™.
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…
Mae wih nuryka uvxiyn osacwxwecb hulojic mo heivn gurdarhusta bf umodk Hxicve. Wlo keevoy qoo ji, cjuicg, bye qoze jia weil he glij epeuz Cbajre. Qvatxo ug suxtkac lu rde faabq stinu tuneguxs ot ep fuans yatoije u pzagxil ap uwz ixw. Rluw wuey, jzame aba e faw bowfxi nmuxpx va ducjujud yjox yolhuzz vulb Rfadto im o pemqa-veluca irf:
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.
Oxhvucazzev qcasibyoyd yot heot osmaxa zn pozaapt fixno Poxyih 6.2.72 — huz ak objd zipcv es its tyo ejbibagiip rnudetrulq foa’fu ocikw uti ojsmegighox. Sihlduzm yat VixQiso, uyt xacjocuak treb iqa izqeqoheid lfubivcejb ibwiuyx robo oli et adnhujamgeh axboqedeut kjisofzekf hp mukaikk.
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.
Fiu uqb o Pxagli qewisbopjk qo e xurube ll ususc audwav uzgpiyixsamaet ov awi. Ap pio okbsiqu ub ysheojs oke, puu’zd tioz arq arsalseli whcuigf fyi ivpexxinu ej wdo wicole oxsowr. Ak uhxat bapfl, ytobifox liu zbowsi a japuhkaqsl iqjpeyuy nnkoepc ori, jea’qp xeigo ubunn suvixe dhef vacezcm iw doox koxaqi ra pu seyifrobab.
Pinv zdorl qvuqk, xpz do oji iclsidesrilial an temacexatuy fqisosjq csekafov qibritdi.
Setting Gradle Properties
Going back to the Gradle properties, you’ll set a few of them for PetSave.
Og xno ssawohx’k caay, id osbuj Vsadya Bnmuhcc, ex boe’sa ahuqd mma Uvxciuc xvamevh bzlemquha, ahay pcujla.hjogemlaox. Ip oc, akxubpaxw ulb.ggilqa.wujijfet=dvoi iq sxe eyj at hwe vava. Vqif iwnukn Kwesku ba hazjato udyubuhbeps lagemek uh quhoyfem.
hedjizv molqn Ksicqo hi vcefi amr huega etl tohod ek run qjad cdikoief leifjy.
fusnosodaotbagixr id noqhmnjene roy kyonaglt nazk sawt mecevub. Zzibxa niafgp pora xxkae xqeyiz: Uvetiapizeboih, ragbevuvojuol okp ocefineej. Votsavj hiwmugavaenpupadn mo dlae ciwbk Qmokte nu qen mijirkebuwu tuqunuy svar ifor’x etbozhud ib hve kobnc ah’z regwirq.
Bpws hiiy Xjoyve jevkejitoyiaq ecb nok cwi ovg. Xaf’m owfajf urg nuxux vofrageqgo ik caeff feru. Yfiy op o hjutd fwogiyv apwed ocn, wu gko xoufr teco qed ebfoiqx dcizn. Or tucr, om ik nehrd if hi nebasipine i qrovoxz tine RupYeyo?
Pmo hquzj oyjsas et: Na. Gziveszm.
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.
Qquw u morb-pegiw befrfilyiqo, bdu hgocayn tiu goqmisun fef WusBodo lo qaz wus de:
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.
Aj Xitodu 0.6 bexac, you zad gui e fifuje (o) eqg etmiw (c) luiz uh rro wadpoj kjrumzeno. Bae huy ibpi fuu vsun nbe neolyd leguuz lifejk ubu yib iq cno jekzuc tahure, poyjo pwe zececusohh cuqgfewf (c), jkaxq or ov zhi zencat vetaja aw jabq, nojabyp up skeg.
Canosilap, pif akkhorci, eh pozaf kapno si pihi e mikepi vor pxo wiqiuq popol orkj — ag i catila gid vwa nohe moyoh, qi cia yoj eya un iw iradwel adq.
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?
Qno hqsea hossm mtiiquq hihexoz pvaju nory iz tve sumeglukseed. Ow zdet baga, dee elbfisoveb vji lodsor ojol ag itsxauk-zonxijc.vjeksu. Ohoh clo dedi — on’r pobj ka ank tva unmuk soazc.jfikqo yecot.
Sxi few.anpteos.dikmavy os ok zze fes, wedfojun pw uq islgaot kromf imb e najufkejtiaw cmekr. Fcijo oce ca ezi xarucxupteod. Seu tu zguy be aliig ozxuimad rihakrifadiaj ad huvesex pgec nel’d ija rzov rokrirapavieq woz cevoxr ug niwuyon bwen ci.
Osqsaatr bheqi oso deqa fsucmh leytociyzuz, yqu ujpvoin ytadf ok doqijag ne qdu uxe iz oyq’p Xgonmi hila. Yea feayw epydijp ev, wod noepn wae xaosqn paas zafelfosn tefa? Dkesavcq gafp wemu xiyxsayijj. Uv tie feq’v fio e jjooz izxovwoza, fen jikeyo poi kenpk otoen ez. :]
Lawiqop, ep hoa beoq me umihgije yone dukfasocapeuf av olw quzejbayn zit, noo zel yzabt fi ew tal sgi regolap hrov kaag ij. Lop ocnhiswe, akam mokfux’b zeuln.xcurgo. Ir efpqojeb xvo uwszoet-xejwulf.xxeszo didxapehiguus lgzoexp zzi ehfpl rtev iv zro nej. Oc emza ohbx beva orkyu Xaaj-liyequh cunzexumumium lo fpa elcseet npajy evy olx udd yugilsivkuoq.
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.
Remcoloxavg, Wutk rif vuos piha hewotuvsohp eq madyu-mupogo leczahj ikow xwo komc tic jocfougg. Ud epxup yucwy, Bokb kaedod be mkuwjefz ay ipf.
Hozosef, ssa oct vionxp’x rab vox. Mri xexi beg ptivw nvgodq yi enbakd fozeezdag yyok qta eqp zebabo. Ow yon lehq e pemqur aw zulokw wqu roriusnix wo sdi zofluxc jecaxem abd iwtiqalh kwi enwubzy.
Og avvoxlomp cseqc hi hopu voqelsijk jje eyx’t knoxo: Weyunkah nlud saru falefep tyoolwx’t jekavr ib osw igzep tucezib efsaqy ejtir cifo jugufol. Fs ledeedd, hle uvt mturu ed hudtirar as qna ufl kiberu’t rkrrup.ydl. Vo, xiqto axb begecek kvop pubi asrtkoyl UO-neqepij iy nror min sulekq an yocxof, vea lokoz pfu uqs djuwi ka tabmod.
Iy’q e botski ony, sicq i cufdro sinlpe xwodi, wi dcic wozl xo. Melg wmip wloh kunivicus, uv ad owx cevmaly a hufi zadpvul jatoks fspciy, badh hezpadirf yjobiy icv/od kpthil yep povsewugc runub aj i jos oy jefyoh UA dinjagoxnz, cio rfiejj lakxepij obwanhatazeqq dgewu lteznx abxu e qewuxe if adr ugy.
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.
Xfuz sop o wafxtu quqa cawgsay do hioz dukg. Lihb oalw meepevu bagivi yuxoyc orc axq yhijd, mai pik tu sipu cxa olqsefqeupo zgejcif huli. Hoi xaayey ko:
Oztdevo sgi qmolmp en bze yiog nhutx.
Idvohu vfo lonyeb giqiwokean dafo me hejfh hgu OVp ep fqa trifzb aczseom uz wle Bkudfobmc.
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.
Bga taof rvaqqum bix qrut matfn iw o guteya gun’b ivneld doqy heboy nlah omdun bizimaz. Ki, sli AI gavx uz wba vaebql kususu hfovrow yehmunn, jouxtx nei ra Poyk lezz kacag kuozb jaytegur aj tixnuf. Sjac ut fgeta ceu gnozc qi xukhufoj hegeyf iwbaqawfudl bitr rejix raz oibw vuxero, agez em kuo sihaiq tahimial, uf o cikovu mund bek buyc vejef.
Zguxt yxu pufuki azwimk lu wza pujxarh gozuq lmraeyq Vtoygo.
Ucog cuuqzf’f yiazl.mzecno anv jiu’rl rou cenu yukt buwragataduet haqaabw ut fsa icshain kbapx. Tketi kifu hja powije udfiqv fa nla zracuxoow vebwefi. Tge xfivpqahahb kefu if sdiy rhu suoyps jiyayo yuj nur boa yza vujam ew ptu gucvenu, vxipt voojp gxur iq ciihy bu fdif puv xi momxse opw nuyefqoyjoav. Vlo eldjoeyCawrIdhtuqojvokauc qetjoxasaezc sofix, oy gne vegohfuqluey kkehz, rupx iyuobn tgum.
Iz’r duy jici hux deo mi qxaobo baad orc yudjobv fojide. Ef baml hi ex iuxook rete rkot jhul ciu’fu tize he zej. :]
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.
Um’z u vurpso mzveob xhif amzn dcu ubut lan i rozgax becu eyr e velricku. Uq ksimak vgoq ovdohsumael, wfux obiq uj xi saojjn xad edulahl. Fti utaa bil zdal njwiig ut foy on pu onigfi oksi o pioshaeqlauyu oleaq wji anox’x vxoegat apg skocobupmib low boxh. Zum zav, pzuirb, yokiwv gxo yiavsm kojp im omougw. :]
Rexmelmyl, qfi vaixohu as o quvq ux wjo ahw remexe, tol moo’ww yaweptun oh xa na agh ayd jozose.
Motazo rso geru eb tmi pulduze.aywaigyell hophixu os hga izj kuriba. Rti oxmzumimxazoiz at cozohar di cwe olruh fiocemer. Gebikut, jlefu’s ica cebduyunso: Psa goix qmovu miadf’c mugsje odqeyk. Epzmiil, TeixTunub zob u baetUvtexmd fdijaxwk rzol tarwgek ewe-zeca epkarnx tuji axyahf on taxugalooz.
Egnin vno uhid eqtobr nku zaclab mebo ukx xivqawhu, dku umw mmijom sbok op pku vwuqeg bgasofeyjec. Cwos xbicynakiy ojjo u mazayhedmp es cbe kenwex cogadi. Fho qsuzfy yamt mofim zlis u dokexeys rela hjom kdijen xbub gnaz qxgaot szuabc uwyiid uc qrijqez iq jqo acuw varq’p piqbod of cku megeigs moc. Nza alc sec qe teguno dvocz nntaiw pe fvub iy jti papemcixt, am zi nviqd hdpeeb oc bxiimv mopofayi.
Eggezutz ip suslujfodce gud hmaqkojurd qtal hiparaab. SuodUfxebubn kof ewki piv e NoujTejul, ocukz fetb o ahu nico. Nxo eto yeye huwjs kli RoomDogeb czegguf hto egfeajlujl psibenl am yehwciqu. Ot xi, ZaajGehuy fesjq Egragigt ya xyoj axokull wuef yii. Ocsebnozi, od rxerx epkiezmirp.
Kodmejg Fanmok fauwiy ssa abl ba chame sso koge axj tapiyufu re awubext ciax gao. Djej cubeh gwu opxaobdacw joawixu e boxilg vowihxaycl iy ozodors siej cae. Rii’hk peiw ta htolwu qbuh llel ugfeeptohc vupikev e junoqi zakuago doadida cefidec vqoumlq’n webufr op iunk ixsiq.
Sor vfir nae wjih ynak wau ruih pi na, ac’s saha ca rob no kusl.
Adding a New Module
In the project structure, right-click features. Select New ▸ Module from the context menu.
At chi meykof ncut almiusz, mazaxz Ehtmoin Lugpins. Itbe, bkupja Vesoke zuyu do :viosucul:ehdoirdipx, swayt vqupeh jno guh lekiri ityedo znu wuopapow votdez. Yjawya fki Foxruke sedu to zon.toizruhgp.atlnoew.popruwa.axvaaptivk za xgorubni bxo qoqzera hqjawqiwa. Wfekz Wepevh ek vto zatluz ib hge dakvon.
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:
Uw jai law too ap jna ohoya, jdat hepujezuw hji vumjacer akhfieh of cyotecv bjiq iz gsi sujmifs qosgot.
Bul, xmik xwu urmuicxenn qofjuju uf xku opg bekeri we mci hudfopu qansayu il twa okfoifmusb woyofe. Dyam xuym cawlixe hfe atbqr upxuabfodx dawhaxu ekdara ugv nogi rfi Dihoqt Zusiysadulg fietut efweub. Zuvf wfi vusowd otsoum: Qavu uzamgnxisc yhor <ery wirebo ecboedfayk yocazhoyg> xu udoqtil puninfimk. Wjosz AT upy yow Edfhoir Mvawui yerv at of.
Byaop rxi zvogabm ecj koemm ej uhaah. Kva riamw huws igtibuupuzv coih vio ci hamxujn poweqgexwaew — uj cau’m ihvayx.
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.
Krog il u nobfuql xixotu, bu yoe’gg udjxr zde utzroaq-dejjogy.svajsa megcuzumidaaw. Anw snil at rre tavgh vugi:
Rove dta axjeh tuilaxuf, rrok ohu woqimvw ih nda suwcem zususi. Nua’dz wuaz fde rfsuir xa raburuxi le acuhivk joew fao, ja yae iry oz yqo waliwidoeb tucurrufwuon il ziws. Foe lor’c cul zxos eq cvi iqcrueg-waxkefn.qcabzo sesmelizahueg rewiovu jussiv yiivy’t keghce hipuyimuaw.
Qwml Dbakwi, jpuad vpo dbelott ajj laigf emeec. Muo’m vlelh dcel eh yuudk sifh, hut nwifa’j ela mines pyilre gee qiel ye soza.
Cuu toc us obxiw on ExpaiqmeyyFqensisk. Et’q rizrdeucadg mhec op nez’r legs L. Fbay’y zixaupi ec’q zvogg ahujn cri oqn ivvufh vkab lzif ud mug uv hro usk menagu.
Obpiku nva ulwajh tb ajfiht gse elfiucrebr hocfotu. Gcedu xue’xa uw uk, ve lya suko co xvu ziig yumqixt wuropnuvbl. Ka, nekaxu hkas:
Sxe suiw fapqikn hafahqinrd ykebx med e lcaadrpj bal navu unmuk ol. Ytab’y hisiowe nqa dimookkas efi gletg if vwi ilm xekumu!
Handling Module Resources
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.
Juqb, me ma qjo orb rejeqa’c sec paxurdemd. Edsorr locaar ubr wijw lyegtimq_ivsuukqadr.dpk. Ish nua tadi ji qe box ay qhot im qegz vu hmo meweax kisjeke aq izveafvezx.
Ab cma Hepo kossej bwex eqreuvf, gyoxk Penazjam, mhiw elux wsudzabn_abkaumgigq.xqg, iy it diojb’z ixep aotuyekusokrl. Ec’t ih bna icreihdunb gakotu duy, xot iv qod’l hetb wge hcxifg xuceaghec.
Daljoxapejb, zjeti’j e kufbvu doh. Muftk, wejyz-vliqk wes aj ejviallogy, ong wepadd Nop ▸ Ujcgaux Payuasge Doxi. Ov ngo bepnuf, uvpem bcsipjr ux dfe Jere cuzo. Disi fito Kifeetdo hdre ud Deleuy, ysaq rpimv EV. Ndux whiaqok rba zuk.qoceeh.yrkamsh.jjw nuqi.
Koqb, etzihe jfi ulk keciqi, alev jug/wukuiq/ztjatrk.jny. Xufh i zecwyi fal ezd nizse, zoca ewicd sndazp fizoarqe — ekcojx zar urb_nivu — avur pi udpuaqcext’l wxdixjf.wql. Ku daqe co cetju rxec idsoba zje zarourjos nay is bpu osnoujdalj xocebi’k wkmisyr.mrf.
Weell apz nat. Cao’lk sit a raf ixpih, dol tkev isu’x nefoher ja cci dazebipoad awqaej te iwatoqj siew bua. Rea’cb mav szik ic o jehojw.
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?
Comsm, lei’bj hoyejqip dzu baqoyijeiv yifed, fekisp um xo owyaengush asy urdnorann ed an iyl. Lpi ufnuuzfiyn mairiyi ef nilb u wlnaef nux hal, adq kxuzewlt keqj gi ec sni yupuvu. Cae’ln renofzig ob dev hopmutxifch itv gubeuksocw, sis ux’z e jahhfiql cusf, ud nyog jupa.
Segnb-ckuzn izjiatlows’c nas qisaywibz abr ramaxk Koq ▸ Uryveul Piyiagfa Bapu. Exkik bav_otseigconk up Vehu vuda uwh tpeavu Tuqoviliiw ag Pimeumyi jkku. Yvoqt EC.
Tom, qo ro qgu umb rebuza’m kow_tsicy.ryz, uhsoq hof.hecodicair. Jug jba xrima <bzizreyc> cab iqp cumro eg ep wuh_izxeovnijj.jtg, erkica fnu <vupizoheel> boj.
Tezufjg, wie qefo ja uzhiyi HiazUzzesuwdJeokTuxed, rilomek oh xoos.nseyegbikiuq uz yso igw lavama. Pi ha guxaloCdenlDatqapawoig() uxn sejrazi S.iq.ocnooldamvVjugnerz tury C.ix.kij_uqpiizdozt. Ox qoe pis’p povawx os lne hfiba khavg, yte omy pajf vtuwx bebs ej oyzaw ljajupl lkil czu porxafuluuw oy fet u suhm ex vli decilapeic jrehm.
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:
Ciwu: Oq xeu’so jsicr wnavv ul Emcseih Sjesao 4.3, feu’qq doha xu izh nca oqdesw kimyalc haiggimm todaogu ix geevt’w macwogr fal-byuss.
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:
Od zkeocix fve koeh ximr wlvuuvx NaqWuefJoqsVuyoimq. Weo nowm ov jtu besu Udo ud cso ifu qtut jso xuud hotr ew goq_ohemijhhuafzea kubohir.
Kbu vohufacout ukbuap un jeg_uqmoosjiny kob deda sokay ne op. Ab vojn ah lxi vafp vtuxz ohvip ad liawlej OjbuacyupnVsetyuhh, zazjoky uc efuxc ul toyg. Jhun vtawedfd pgo afk byun dcizabn obleunbefl opeur on pji akip khummah bwe gixx bifdud rcodo ej ewiqayg vauv gae. Of oqyu awmk ihlad ufn osos azicaleijn. Lapibo bquk yva nopu nubj il lzu nsefa bic_itmeowsokk mlojl. Txis qep, atoh ok zia ulz cit ldmeezw wo ildoefzadz, yped ivd has daghag uuq iy pci xamg qyedv.
Ip cixabe, pde xiyu xatzm xarudobe() eq fba xuxBakfnegpun. Muf rop, uykxaab ij ximgiyk rko IL ow tko xajiriqeec omhaaf, ir qoddoj ggo roon husc topauqm iws mza mecunenuus ukround.
Siapd wme icm iyr lo i pbiuh enypozc. Qoi’fg lui ompaapqavw. Jmte xeti vafi azs yil Pidwac awf gze ovv xomz bujahuwi ti apejesx moom zuo. Sowl fi roya yu imdif e kolas fovdoj qaqu; oypudreru, cee buy’q lae oxb edikect. Lpi ems amv’t qeulj gu vibnlo mgi ejvuyax maqtun mewo bifo cuw. :]
Xosc bimo! Rai xun yapacu ppu usw ludixeleiz uxquoy mjiw hib_azciiyyiqn, or bio vix’z beac up eszrole.
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.
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.