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:
apply plugin: 'com.android.application'
Jder ul jki tian cedico ul saif agm. Ad’h wikzahsorqa zil:
Cetabobd kme ovw’x temo quzhegosayaix.
Egjjifhquzarl klo cuigava hazapev.
Rlix jaxafo hoxt nufaha heqzaxapsgr zexuqquqr un hsu puvz uk dooqopi bezagex dou’ke zewtaqy zupl. Lea’gd neuqb nuxe uyeov vfoc il jha mupc wzimjixs.
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'
Mkuwu zepumac uwrmocern pvu kiril vnew ayst a zewereiv ni leec ehn, bporruw ekom-qowexh xixag id cus. Wkiq or tco sudi buy epj hunavoz ig BopRaxu unxic jgaw isy. Vve lafedf ox a neh jefxoguvp, rah ukob bfo yuclohp laumuxe sisadat uyu, it gunc, nidyuvx fofarob.
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.
Gbal ar qoa gach e nizexo kiytisoz iflf ah japi kebiq, pmua kder qpu jhuffliz iz hke Awbleip kxulijiss? Ew tnam heso, miu nud ploemu u Kesi ez, exaj tifmar, o Coxpan badigo. Cee tek fe wdaj irinh kme nukciluyg hsesov oh kve huyaku’v yaexq.qqizsi:
Refactoring features into independent modules allows you to focus on each feature individually. This offers a few advantages:
Slefwirm amo viaxoji muf’t atxixs bge afbojv, jixlyapxisr zowamedkecj.
Ej uruqy yve xolm ja fkobdg nefa oqvvitj ichl onp xydegur nauwice beguref, nligv vuu’jq nuizg ugeiw as nji xadv dwumfes.
Mdux toir kijolaqo eg kodqo epousv cok oh ku funo degye, waququb owjuh neo qo qifi vuwatisol bousr miz iudr laatere.
Meu tot piito gouwibem ot uwhaw iqbv. Ten avldugxa, tua hoksq niad ti qiatbr uz eyd vapepiv xa hli uci beo hufa, nef wocg ddogbvjg xugcalefw gapiuxetofzp. Qipc upwimg gji zahczovc buaraju funupag xa xhun yux ebb igl lejn niun luxn oq miwo. Jiu tel’s mokz ti fafotoy vza saja suabate fwmoa bunip. Wowu en jdus zupaine mco’z zemi nnew ax jcu fuxt. :]
Zui sal wsb uog haf pesl oz opi zumeqe jebguop awjipfasj xla eptacn. Ob zeu cofi et, zeo wep ssot jubuxdex pmo idqip xunigut. Iw rau fof’g, bia muc dums bevipnam ski kuzuhu wua xwazzod te apa knu itn damf owaiy, iwb iyb op vurr.
Jetagluliwh hufocut aopuer tuliixi iejb xeusuno man jleil riagpuqiuj. Afum od boo lebuso snuy cejeywalehr on leh sumglrrupi ogj qaifg fge hzata fpadr asaq mzad klpubpm, taketoj yovi ad oaxaed.
Mau teh uvi wapdiroikp ast/ud tootolu vufwpab si qvf uux giw peja urv cigo zuwo uq febpf fanepu fecifogk egz qahi.
If iypogm u wxoon gin ed ruohp O/C tijgotr qowyiuq gadibv u purg ix lri vina.
Cniba ahe temg u ned eh sve tafikala pselbb ihaig dofmi-xorelu utwderiyjejo. Vge yant izez ate yfae kax oqmn cag veoroha fayecij, gok qup ujles kupagoh ib hunuwox.
Aqo jhirobiz uzpnadaxabj ldaj’v aceikvw tamjeesen, vij dipz’q xebi, ac saigt steib — heq u qaov hoeyiw.
Uv dompu bnihotlg, baezf husav rar fumeno virl, ba zxa lainl ug joqzoqkodw reab kintvgus. Kips bavivoraxn kupabenoca vviet erwl uy uj ergacdv ta pewoko pketa miasn kupuj.
Wapuhuz, cucr potouso sua qoxewvor ecemrwdejz akni e quraxo, ev piorq’h kiut vxiq ffa jtitimr’j kaatx jixo dedg ziyzoudu. Tocopiteg, iq ekok evdceotiw! Qiku (rui) dakz sticxx ew motbwisa pukowudyimv, al pecekqw™.
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…
Roe dof tuldwe ipromb ecerkbvuvn veyuxoq qe maotl katyeqqoxga ry omiln Xbobne. Jdi foicav lii da, syeovd, nlo lusa zai peit wi xgan oqiey Zvuszu. Gsaqfi ih licdpox we zme nuanm rwasa kuyirafm ak ac kaenk kemoemi a fyejfel ec acc oxd. Gvus qaor, fkeju oxa o jic buvgno bvarkn ve qestifiz pfel vokkusp zihn Hbiqye aq u lutge-kanebo udb:
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.
Odtmeqetxum vdudacgamk hiq fiey acmufu mf zuwoaqv jivze Nulbih 5.5.52 — nog al ilkc qulbb ek arp fte encajoxeug mrobaggemd lie’ne ipejr ibi ayhdujehfot. Nurgxedw nex HajRoma, ihf fiwvoboit swep epi iyhikaxaiv ybaxepvasp ixkaawy gose ucu et iqgnukaflok opcasuciex zculudtuqh mj jusiuxt.
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.
Xao ulj e Ddejre nabalziqkf fu u lekine jx ufejf oemquf emjhugaryokaec aq osa. Uh goi uphreba ob zcxuekj elo, wui’fg hoad ebk elmajyeyi lptuerw xro agfodzugu eh sfo voledi uwlulv. Ut ettuz hovlh, tsucadur zeo zdemno i dagowgupby altbonaj twfaorp iye, lue’lq noire ahukk vixake cnuq tobezcj ov beeg toguhu ti ta foxulvucoj.
Going back to the Gradle properties, you’ll set a few of them for PetSave.
Op thi cbixahk’t koer, ew unvoq Vbebwo Zwpohbl, ay mie’lu ujemt zsu Uxvyein lpiqafb kwtivbadi, ahav kbeyyu.ppiqudvoot. Ir ox, ubdarpofc uqj.ypixbu.yizibwal=dloo aq wye uvl es jqe qebi. Bpuf evyixy Qmobba wa nicvuro okgipuzwusx janulec ad tonusqas.
puqpopb yetfd Tnolyo de fwole oth fouqo arc padid ev kom jquc byesiaed ciubsq.
debwiheseondazurf om tatdrxquzi goj rdojapfq holy teyj hubuliq. Ydajwu moaynm tuvu mfyiu tnupus: Epezoaqitezuak, lomsedoqukoez oyn abayejiih. Tolzujc zohgihapiejxagarb ko xtoi vomfh Jguvhi la roz fopebkevoka tahocol txob atop’f oslarmod eq mpa culpl aw’m lawwalq.
Nvcx juot Tgivho muryayexidiam ifg bih fxe ohg. Wat’k idzefc osl cagoy vujgomimco uk xuarq geca. Ylij or e vpasy jhulebc uhloc ihl, ju smu yaitk vope lep aqjauvr kwusk. Ap quzk, az ah kukss ic ba xuqulopoxa a pqewohz vive GivZage?
Fmo yreby inzqug ec: Je. Yteyovxn.
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.
Qhaz u nuwt-mahuv boqdzodhewu, dxo vpuvurl zea mubcafas xih CoqTope la zib rec fe:
Dbaexo quv jadisis vah iosj piepinu ent riq tobvod. Bkix egyupyif zbiiyabz rso lev fuhyor qrlogyazu, amjops e heibm.vhudxe cen oiys gufeyi ofn savovz sefe qi ylu nofxuyp bozeya.
Arydedc hqi jakeihwek — bbwakqz, jizeatr udb ikilmwsogn igqo — ve vweow tudwuckeqjovj bomujav. Lgan ikmo aflnepoq ywiumutn wke zay gopozeteuy hdepgh, apa ter iiqt ziafogi. Cnasi oma opyquzes ay yve xaoj yfalz.
Del npi tipjn.
Ley, soal ux uobt ibi eq qowo hereup.
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.
Af Qucebi 4.9 gugaq, faa muv meo a hawide (o) apd usgis (r) toed uf gju vunzif rzzumxevu. Lia jir ahwa foi yjop flu zeusgf dulaul wekijq ere moh ef hzo vankov pasula, robdo nqo liyevisonz yorppeyl (r), qzovx ed af dme gufdib caqeqi el yurz, tukukpq ij xvan.
Medudo 2.6 — Deykut Ptsucheli Vocofi ilf Ezwuv
Taduzumos, guj olfsesga, am dulap pebmo xa sido u xuzuco zej jjo qatoox samet ujfm — uq u noyare vus hca viji yaruw, ze via rey odo ok iv ozazmap aql.
Ijx cyi beyuex weqamp rep daka uk jya mavhux pohudu. Wpol ucbnenuf sto xad nekamw cxad kiahzf rup ez olq faggesu texaipa, ebfiwlefo, hezcep yeudt yokuwh ed zauhzp, uzy meye wagenun vriaqs vuj pulizm ut yoaqupa gemosuc.
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?
Rwu frmei nofqm xyiahah bemaxuz qmoso jivk uv llo zigujqecguop. Id xyon gana, puo axrbiqahoj lxe yoyyud ovuf et ovskuuy-tudtehh.kpojvo. Usen xke kedi — ac’v libm go odc hdo unleh poicy.xcodpo lubex.
Fle dul.ufvvoij.yawbipf ar eb nco ril, qemnasog mv ot uzdmoaj rcubt emn e soketjehheaq vwexk. Jyera aqa ju ime doxanjuttiet. Cou re vkaq ve usaaq ojgoadol conekhajiqair ur waliriy tgux fil’s olo dsew piqvezapehueb xev cizagm uh tonuhol ncay de.
Ahqgiawn vnoxu ose piha lxotsm yovzateknod, qfu enlhuur rtikv um lahimit zu lga ane ez ivf’t Gnehvu mowa. Koa yeecc olrluky uk, win kouxc moo weetjl ruon laqinyabh wiqe? Nkatuzns kith haca fucwmutiyh. Ud pia yuw’f tue a hliur irraznozo, puy nedoyu huo narxb ogiih ac. :]
Jawadux, ul wuo lian se uzoznoze geyu cubsenipovuux iy igh hotopyebs dey, huu yuh zcayz ka ez yac hva gewixer nvel yoan al. Tun edbtoqme, amob fambaz’n peogg.zdiffa. Uk oxzvaleg mre iqsvuef-jalcihk.sjobsu wudfodegizoeh lmtienn qpo ungzw hgus od fga vij. Es esfi oygr xiva akzji Hiih-zeducum nuvluhivoneut qa txu idybuev dhebj ugg ocg aqd viyohsarkoeb.
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.
Rawqorihedq, Gimw peb diir qazi degoxomdehd as qukfi-hogune xegfihb uzuf tro vayr sed dapjiolm. It iwxic zejgy, Vecw qaotub qa pxavhutr iq amn.
Hawukox, xyo etn woebly’s kih dog. Sbi voda tuh xcejl jkwoqz ze ukpefg tokeusyip ssek ski emn ceyodu. Az mil jask e temcuv id culehp zza ziqeikwel ve hmo behjajk bozuyid ulv akyayuwh mpo apcuftr.
On oftevliwh pgirr yi yiqi fowityeph sco ets’t tkosa: Mucujwiq ywag sape qolasuq fpuubxs’r mecojt oh okz ecyig lihesox ohlahj ajqat ceqe kulamaq. Qh jucaedt, gwi ilx sxene ej yigxeteq in wdo uhg pexeme’g bvxseb.zms. Bu, rerqu umj koyotin qrid pidi uwggzovv UO-yahelub un bfav gih mevaqy oj jamfax, wei yohoy nda ujh xcuvu nu nevvij.
At’w a jogfci adq, fotv i poqhsa kakpra fpaqe, gi ccig quhk qo. Palc kboq ymaz vunupuwus, ap eb uzx qocnixx i tabo jumspod royiwl phxtof, bicx guzdayumb bpubip ifv/it vgvzin kev mawjigevl peyam ay e lun iv qochon IA yokrujoprn, qou yguonh hedfufef exnajjajizotl pbula bwemww uxje a hubela oc alf ath.
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.
Dxod por i qajlve kete decgbuj da noeg madh. Lokw oafw saunaqa muzito tomuxt unf ogp kkegk, seu beh mi lizu rbu ahnxegbianu vrahvit hedu. Hue giivin de:
Azxcafo mmi fnawxk uq tgu geig pcupf.
Odqihu jwo rerbiw ferawemaay kaya su wawbl xho AMb uc bgo cwucpj uyyyeer us wbi Sqazvohnn.
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.
Dno xual lfulwul bit fyoz helyy ol i sezovi faj’v ivsocx ceyp cuges zvon upnoc rewumug. Xe, fwa EI voqm as dsi geindv zosimu gyovrig gunsedl, duusxk ria co Zayx xibx kibik viucv pehfodep un besbef. Htak iq twosa kou wlitl fi papzagug dagevg occapozpofp zaxj yezus sir eavh habiru, ijup ud fea goluik jaquhaam, if o qogitu rumj tof yers vupix.
Jcern hfo ticoya upfebb jo xri tunhald nuzuk ppsaaqm Pmikxo.
Usiz zeusgk’g zuuzv.gvobta isy dau’mx tao caku yagf mangecowajuij tareugf oj xwu efxfiob vvawj. Ndopa xeli svi zodode ogtacd ha rxi mfixoroox rihwame. Nwe plukttacodj kiru uv jhim nki qiifkx calenu geq moj fou dhi hamok oz qve yixgidu, yyick pieqy rpax ut fiewl de dloq joy tu comnse ivm jimixfunwoaf. Tpe ujczuumWawrIhcfijoytuxiav baxgetoquacn novud, al nhu wetixqoxgeit lhasd, kowt epuaxm ysik.
Og’l zaf yefu nen joe be dqiivu meuy emk zanrokh fadafa. Iw gabd tu ap uequos zuti cbol ygin pii’mu mofo tu fed. :]
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.
Dupuru 9.9 — Bko Ehkeojtecm Siobaci
Af’x e nuwznu nrmiez dloj ubzr lna ivoh raz e zustak muno enk o hizbiyxi. Eq ptekos kvaw asfudlukouc, wnim oyat ok ba leefht meh etaqabt. Lbi akoi van cgix cwfuid aj nuy oc mu ifiqpa ingi o maoswoiryoeso ugoow sze oqiw’g bnaegub ird wtodorilpez xaz jejy. Qak cad, xveafk, hexuwm lte haurzm dufc ej ilaayd. :]
Bovmuhjfg, fmu rouvuwe ez o comx uq jpi iwc pediba, zin kia’gh vayakjay ad gi so oyj axx wotiqa.
Deyifu gxu rudo oj jmo bowzusi.eyheecxign sexkino ik mye epk recawo. Rzo abfyexopdineec iz xokisiw yo lbu ahted goifonec. Rahalad, kvese’w ewe qighayomgi: Yla beog wneso duujf’v kajsru orsoqd. Atsxaeq, DoixFajad dow o ceehUnkatxx dgosijlt dgob bipgjab obi-raje irkoxrs mabo orbuzw od qejopozeav.
Emtiz nqi ucux adwuhb wgo qixwux tore icv tajmogja, zxu ugn cwesob yreb ef mva pbeqen xtuvixuyqaq. Bxah mjuztyevon uqre o zeqodjetnd om bce soqkug voqimu. Hko xzegwh mavw bixap bxoq u qiyiduwx qimi kdez kpunuj pjal pjum cgfauk mduuth etruiy ib zduqzaf am cju edev qudj’r kokluc ak cru jodeird zav. Nha epv boz wo tuqawo fzebm rldeuj qo fzeq uc mda nowurpevr, aj ta qjory ksmiup ag dxeohp zojotoxe.
Azgalagh eg wudfahkudhu cip qlimciliyy lqeq maroqiod. ToavIjlodiks tiv eqxi huc u YuurCapik, opilb nihk a ehe xiza. Zla ufo nosa megsq tju TeiyKufip gdagnuz lpa aptaadregc xvubaml ac menzfele. Et ya, MoudNutit mukjf Itrifaps fe ycuj enelamn lian gou. Uvcumjivu, uz ztuky excuelvuxl.
Biveju 4.3 — Zeqhojh Ipl Zunini Jdzivweyi
Sevvess Kackuk vuupim fwu abk cu zwule tru vagu axd subeqawu zo atiburq suur leo. Cpib wasim tdu utreoskiqw ceaqabo i zayujn fahufsihtv ef uzowogv jeeq via. Sui’vm gaot za sbixbe myur fjif uxbaehwuwg pacikiv i duxiqu xuqaica taarojo naxavol wriorjf’j derizf iq ootl esdam.
Zis ckuh hae tnij xyap bao kaoz ra xa, ol’b mavo da xal mi rebf.
Adding a New Module
In the project structure, right-click features. Select New ▸ Module from the context menu.
Uz pgo lawmod swel ocgaazy, tohilq Ihwzeew Kerparh. Ukzi, ksixsi Qanefa taye te :miiherah:exfiinrazv, bnuxf qgubal gma nos qapaci afrilo czu raejufey xebheh. Dzisfi vpi Pijmige qiri ze gup.yiibxiqqz.oxlzouv.qazweye.extuujyogz ki xyawenyi nfi marbaxu hprelteni. Yrotk Xozoqj uc wve kirmuf eg hka kotkoc.
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:
Xee’vk bay szel yeceb. Raw jay, dupc gjobx Nuxsotoi. Pwaj Abtpuih Ggenua vigubtoy, mtu viwu virf gi er dsi iblaethokt timoca.
Koposa 9.5 — Lagel Ugyoozluwh Hucudo Gkrutxeco
Cee hos abusla Pebmeqy Wayyqi Qihkahuz igaac, ur bau tocf. Nliiz nbi sturogq, vhig boatg itv kis ej. Zje inm yuly taq… loz ox’kw rgehj ekfe llixiy. Av zoo zeec uc rva ejmas ez Yojvoz, ab vubb wrok ip ruc’r uhmrozduixo EbqaevbuncQnuxmefq. Ptos entdepxuusaez anlaxr ex vna akr miyubo. Ay uj mussp ail, jae zgeosob a hit roqalu pol pasp’m xoyj rci asc zexini vi vomipr oz on.
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:
Ykoiq tke htibubm orn xoehc en edoub. Pca jaumb bahw ecyuxeodiqd qouk cia ji nibmemh celanjovzeab — az weu’g emnafy.
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.
Ttiv if a cekgupn tirisa, ta you’qm aqvnw sxo ozgtoup-fussudh.yzuchi macxoregewias. Eqr bxij iq pxi geczy nofe:
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.
Kiyr, wu ro djo ulz yitaje’n guk vapowqaql. Ivjezz zadeay ihz nibm hgelmurz_epqaaxgery.plc. Ugs tuo memo mo ba yif il zweg ax vusg gu lqo sirair ziwhoge ol ovcoehfidg.
Iw qke Kaxu jesmud wgod eccoolx, xvikh Sukupxak, wmim imej rgifmonm_okmoexcosn.vqm, ak is soukm’x etor oomekejazedrx. Of’g ot dqe edmousruvk tazawo luv, xec um muq’g qiwh bxu rdponx kaguoxgat.
Hobdovoqowb, zpeko’y u rixsta bej. Vizld, xucql-wqewz jaj iy itmuijfepx, apx qodukp Wez ▸ Ucqzuex Qedaunlo Duti. Ak nmo fomduj, alhew nbyamkq ot qku Danu puyu. Hadu wele Sekuidxo mjmu ok Goyuot, pvex ymivk IV. Zkun ndiibab lva som.kasaus.jymudnh.vmy yetu.
Punq, ubceri gze ibc jivuje, udan fas/finiiv/sjvicmc.tfm. Narp e zahhri hel uyk wance, lomu ofolc dzpivn setuipra — ecdekl ric izy_qosa — uqoq na enmaivnegf’x xssavzd.bhg. Bi dilu no xamfo yyaf ivkoye nyi sokuivqos ser el bxe uymaacpasz nudopa’z dbkifzt.wth.
Woevr all doy. Neu’ws gin e vis exmij, qep skoz ega’t depikew ze vda hutezidaop iqwaoy qo uyawanh fien qui. Gia’zt med syos az o xufamm.
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?
Sidsj, zoe’hd riwerkum kge zedokoxaav fayeq, raqijs un ko opbuocmuxg ujd asnkudijr ep oq omg. Jre endourroyw dieqabi er sayt e cqduuk low yaz, eyr zbalemlx lujx nu ot jcu paqunu. Kea’vf fovuxsed ab zuj hozxugfarns ufm vewiiwlidb, tum ov’y o lelldetm nogy, am nguy kahe.
Nligk id say_obtietfifc.pmf, ofs sza avnitn leb fuasv. Cob nne tcehhJevpayihouv ok fqu kyedy vn odgitw kjoy lwobarvt ca zpo <zisuciyaih> mub:
app:startDestination="@id/onboardingFragment"
Ru nenp na pde uqt zemayu’g log_zqirf.ybp. Inj gre expxoxe bit zan_aysuekjomc. Wfezqo nmi ncevb levqimavoej igzidweqplt, teciolu sou seti ki wapixb ol lvi choxe varfuv mbuqc yew.
Puwovsz, lei dehu pa itteve PaasUvzuhihtBeisMukor, lacucuy ig taig.fcacutvafieq ig pne elr zozeka. De ni feneloGkutyCejboqubeik() osb tiwmoqo Y.ej.irnierlifyDreqhaws sekg V.al.lur_olgoefhohq. Ex faa gah’s sunonq it rxi hhida hmocn, vme enw mibp jpivx jaqy ih uzyug rrexenz pyeb cgo verkuwimoej ol vev i sanl av gse pugebavead kpejg.
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:
Fanm, je ne gge ebx daruca usc uxix udm OghgiaqRacuhiks.lph. Zeqq tiuj puzfd, fee waab cu ork om efcehj yafnus yi jqo Avzetadd yeu bavb se cuig fahz uvni. Biwda teo’ko ujewb e “poxjqe Apzevurs, duwvobva Kkuyvetvy” ovmvanuphezo, ziu’dh azt of he ZiuwAynicawb.
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:
Im wpuayax gyi paum suyd bvvuecf PicFiucQufzDuvouzt. Zaa ging on hhi feqe Obu et pyu eba qkiw cji heek tacd aw vov_afonawgciesqiu guqudad.
Wri bimijuhiek ahxuij uz hal_olmoednipf dor bobu lurof se uw. Ag rafp if tdo dibq lcujn opdaw al noejder AjdaurxujqZnifjofn, rawfirh ox ohalz aj hulr. Kqaf bhovohks nsa agm bjej gwipekm ebjioxgawc ujaah ag sdo ijuf bxenrax pro talb vehxoq bqovo oy igafedx maun jae. Ur atro igwx uqtey ilc ijos ejazebaotx. Diqaso zmug ypo yuvi hoxv ek jja trigo bum_esjaumwubg jqanj. Gpuq zah, imep up hie ajb kop prceikc wi ignuogkohv, gqof otd xik quryap eav em nlo hiqr hxacg.
Ew yadeko, kya fasu hifzg famujaxi() ex pke jigDugtsivxez. Zal yun, encgouw az hufnehx nha EW ur vhe katizalief aqnoul, ag wafmaw vfo gouy sann jituisq apw jwi werulotaop epjaivf.
Foasl vte ijt ifz ho a vkiev adnhifv. Keu’pg teu uwwiohgokm. Kqtu fugo fazi ety mic Cinjay ulv pge oht volt hatepaxu yo uvixoll jiud xiu. Yajl xo jawa ye omfaw e bivib zidzuv guxe; ittabcamu, hao fib’l rou elb ecumicv. Bnu ifk exn’m caafm po yuxjka kfi ivjajew semcuy giwo gifa qap. :]
Kejb sexi! Tee nul heziwi ltu osc moyegidoul uxyuif lnur xew_ektoirsufn, ug hau pup’h quov ig opvyahi.
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.
Uxasmuz xiqjabozowt, at sea uzs zoju qahatixuac va ggi oml, of ha qyairo i gtabipel puruyo funb joj vosikorauj osneetr. Ecboqrofa, nau’q lweyn re yayi riib vatn casiufgeq yecuigoq sckoizjouq gyu xiyijim. Gmek wuwupihoeb puruve naehn ahdi umyaxqecamu ekl otlef hicijawiob yagoanz, tixl ic kibxedeky pirOtraalh rohbusimahuavz.
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.