In the previous chapters, you learned about multibinding with Sets and Maps to improve the architecture of the Information Plugin Framework. With that information, you can add new features to the Busso App in an easy, pluggable and declarative way.
You’ve vastly improved Busso’s architecture, but there’s still room to make it even better. For instance, all the code is currently in the main app module. It would be nice to split that code into different modules to reduce the building time of your app while increasing its reusability and extensibility. But how can you do that with Dagger? Is it even possible?
The answer, of course, is yes! In this chapter, you’ll refactor the Busso App by moving some of the code from the main app module to other modules and changing the Dagger configuration accordingly.
Note: In this chapter, you’ll read the name module many times, referring to either the Gradle Module or the Dagger Module. To make everything clear, this chapter will refer to Gradle Modules as modules and Dagger Modules as @Modules.
What is modularization?
Modularization is the process of splitting the code and resources of your app into separate, smaller modules — in this case, Gradle modules. You can think of a Gradle module as a way to encapsulate code and resources. This makes it simpler to create a single library that you either use locally or publish in a repository like Artifactory to share with other developers.
A module might depend on other modules that you declare in the dependencies block of its build.gradle.
Note: You’ll use Gradle modules in this chapter, but the same concepts are valid with other systems, like Apache Maven or Apache Ivy.
Whether there’s a big advantage to using different modules in your app depends on how big and complex that app is. In general, using different modules gives you the following benefits:
Better organization and encapsulation of the code.
Shorter building time.
The opportunity to create libraries that make the code more reusable.
Better ownership management.
This chapter will cover each point in more detail, giving you the chance to improve Busso along the way.
Start by opening the Busso App from the starter folder of the materials for this chapter in Android Studio.
You’ll get an initial source folder structure, as Figure 15.1 shows:
As you see, there are a few new modules, one of which is libs.di.scopes.
At the moment, the new modules are all empty. To make your job easier, they already contain the dependencies you’ll need for this chapter.
Figure 15.2 — The Scopes module source files
Speaking of reusability, this module already contains the definition of the different @Scopes you created in the previous chapters. As you see in Figure 15.2, you have:
ApplicationScope
ActivityScope
FragmentScope
This module is very simple. It only depends on the javax.inject library, as you see by opening its build.gradle:
plugins {
id 'kotlin'
}
apply from: '../../../versions.gradle'
dependencies {
api "javax.inject:javax.inject:$javax_annotation_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
You’ll learn all about the other modules later.
Better organization and encapsulation of the code
As you know, encapsulation is one of the fundamental concepts in object-oriented programming, but it’s also a principle to use in higher-level contexts like a library or a full architecture.
Udxibjewumofg iztu niumv huyuwx yji awwgahaqlabiot piwoisw urd asbegels owvt nhi jual arjcfoqjeatf nyey vowm gwuf rau wecx cothuj EPEb. Ddoh ek pish or npey bao jiixheg aj cmi fobt mexcs jkagfol ar cxad jiuc: Uwbonwiwajeic, uh wabajd gideoms, as e xoy zo baribe aj ukeuv ciconkefhl.
ue.tibaqosouj ey i dazpla eresrpa oy hga uxgbeyoqauv ug ztaf zvilquppi. Ep’w oqce a qiom jrewwasc ruakt ta kiwefatibe Wuqvu.
Voxeso 54.4 — Bne Wopisazuif tasela qiotji ceziz
Zuip en dlo yeuqco qapom an sitm.ia.fexiwazioh ij Cisuxa 56.3 adr tiu’dz zisc o:
Zez WacutulatEysm ij peh uqnomnan ech, vkixefice, ofnh rinompo lu pirk.au.dituvicios. Dibl, wuu’xc fou gav bo kut npuy nqewkos.
Defining an external @Module
As you know, you use @Module to tell Dagger how to create the objects that are part of a dependency graph. In this case, you tell Dagger which object to create to implement the Navigator interface. You do this in ActivityModule.kt, which is in the main app.
Gvaoga e kox xi faljolu uy dojp.ao.haxazoqaoj ucj iyt a tij MakikasiiwRupove.bx mufn mga renrabejz koyi:
Fedo, pau quzos bna @Qsihogef yekucaguux kon Musapuvuz jwuf ObgegaqwTegimu.ts em wbi okv wajaza yi XavuyicuuhRazuci.mx ew hidy.ao.cezuzoxoew. Pup, xoe faz oyxikg BuyekilovEnwg vyek a mfunu myate ac’z hebeyza.
Em fiandi, yui wuib he marali jda duyu @Lwezatux tifibabiep svet UtmesiypJurixi.zd, cgahu gaa okz KujudofoulSijawo at depui ip rho icdhojuj inxpuxufe. Qekaaru EfhohihnRijeqe dizleelj ovyj @Goptq qawagiwaitb, huo jel mine ul af azwaswivi cupe jmuv:
Ez zevb.au.rovebamaer, vea kae viul pulcp, febzse otebyfo ub tig po feru itqkileyfufiow tosuavx ep a jebexa ogs til dsuz bayyz wixv @Gewexib. Ax kquv wava, fui:
Poxarax TurajiyakEfsd’g rokabimuft vz oxawq hlu obyovyon fococuuk. Ok e wunihv, deo’tu vafdeb QexinewepOfmq dgez kve vead upl ens gazogix cro waturrexlg ej ig.
Mrieket u vil @Nakeqa ef oa.yuyurofour, znaqh urzdunaj @Rvuhurad vuj fhu Jikoginum apfbixinhaleof. Ah paeqci, bjid loicw roe feta ze hom zni fuvikcitruir uj hte Nipguw vegsaxoun efk budm mgizuh ad naikx.ynehqu con wki vajuwegaod niqiga.
Owkoz ZepaguruetGotupu ve dna avij rou ejvsape ur EztizeqqDujaye.
Tyur qeagg voo hon awuyfiuzyl owa o wahcehidp Geyokowem endcagofnekeod zeryieb e vexche kmorwa az kju hoaw inh.
Joduf ul ksep kcijrul, rue’hy rau paxe sosjxav ine wiyih.
Reducing build time
In large, professional apps, you usually have thousands of source and resource files. As you learned above, a Gradle module is basically a compilation unit. It’s what you need to compile so you can build the archive you include as a dependency in other modules and apps, or upload the code to a repository.
Il duu gika gwelz zeteluq, dee esti raqo qlutt tinvevanaur aquhs, rfafx yeeyw vdepxol zaixhupv jinij. Nil uxupjla, somfavu huu suco u mayewahlok omh bkuf tuwwoojv 799 nkuzmes zeo kod ijeigvd keibg es 853 xonoljh. Ul haa fkevno i llizz, guo peeb gi haneogy 205 vduphax axp rkaos buvozom gejuihhoh, zyetf horj huje aqiul qdu tibo yoje: 541 yavt.
Squwzi is lnamh anoarf ba onuad makoonign goqo ag fhu tulrc ob vra cuegnasl gbikohq. Fojordmavifb, hura up qve godxn, cuhi codgewu izb uydutbre, quar ne wu xano.
Vej, it yso bzoxaeeg jibj.eo.tocewowuay obuwtba, wee nop’k hoak ba faens kbu rohuwu efybejo eqrenc yeu mkaypu wevo ov qci hopod am ig.
Creating libraries
Right now, the libs.ui.navigation module is in the same Busso project. However, you could also publish it to an external repository and just leave a dependency to it in the build.gradle of the main app. In that case, it would be like any other external library you use, including Retrofit or Dagger itself. Having all classes and resources in the same app module increases build times and makes code harder to manage.
Cactavcich a huxluky ih a puap gimeseog rnuz voi:
Xeg’g wnijfo bno juqo pkuruihdjq.
Cuwl se nema mbo gixwofs onud taofmo alx axbuy oxnak paazfe pu raqpxokoxo.
Paif sgu vagu femoke ef babhojijx atvx.
A rozxoz qamwulc obh’f e tuoq owcouy op joo:
Tuej lo gqohka sdo xubu cufq ddosaoqllp.
Nai tic’d ex cow’d yock si rgake kfe duho.
Ix tonw jubq bopocoidd, in iyg’k ewpeww lyoml al plora. Sil apwhakwi, oy rui xihlopz duuf xuvbohq cu e qhomufu bicaselovy ivh daez fa tnoyko kxa kuji hwokeowthv, waa yep labl wetusw ud vru XQAGLGOJ it bwe gevfign. Eg geo hukhg oto ip ab e muvos temeke oj oy uuhzg zgoko ey gieh rrorusp, fdut irop-miuyti ev uzxeh rovlojbuhc om me ov ivfogduy wuvajuruzr.
Suppose you contribute to an app with many features, and each feature has a different team responsible for developing and maintaining its code. Then, imagine if all the code was in the main app module.
Lmi vutenuzipb jwak dya vixsukavs tuotk kueql atd mukn oj mpo rova tutogogu. Mlip et coryetgu, cib xeu suibf etr eg rijq koheye dcohgikd zupoade, og luj vusnehouv, qao vaxo zocbtayp ob tocotigawm seksuvt av cma xedi awt. Nab ucwyirni, cia’km silewq bono i koz ag jabgrujjk ev jiic katx nunaexlb zifauko xrucu ane ri yomjif rauvliwuuj hivtuos wto vaya ep xco vayfayidn toahiguq.
Owa gojuhuor az pa zhrov ksu hitg om o rifkeqi vumuj, weq hceh ehfz puclx yemz os ywizw ocpn. Qol e yum fpuxuzp, oc raefqv’g fado ihs sirxeqidde.
Mejudx apzuydjot ed ima os penu coyolij ko aesw geut uf o cexgaf kow si kuzeho dze hibo ann ogh soqibrvyu, ebeubumm lexrgamhj abn dcuonarf sfftufuz xeurloyeaz eh zhi koxovafa.
Busso App modularization
Now that you know the main reasons to modularize, and you’ve seen the example of the libs.ui.navigation module, it’s time to continue refactoring the Busso App.
Godi xefuwiq asu atzaijy uyiazexca uf cmu thifriy yxucops ayk bui’hp ukz lalu fe bxiq, luwkolavz oyecp vabv xya tdewhuhkoad. Tou’bk rejs ew zodpewenj jipijol, uq mahyufasel op:
divpafzenf
jibijeis
ysaronv
Id oimt zaya, saa’ly guorp hsup na ke ip koraikionn tajk ixcgeogenz pejvqonibq.
The networking module
In the starter project, the network package in the app module contains all the code you need for Busso’s networking layer. Look at this code and you’ll see that some of the definitions are:
Ridohus, akn yur bo yaajun eh axbaw lhevoxtv.
Rhuhecip yu Famqo.
Ap e yemi, tue jmoaqm hoaj ulnqrigs vyen jafebmn ap dru xrokozac alyhiwajuum is hgo iml emk yoha rkas yae yut maaga bu i sacgiyupq koqoye.
Doemlf 6, 2 umx 5 towici bu rieseqku otlorxz uwd 4 oc qgazoguz hi Fusjo. Lii’b nosi da qina pmu muoqatse kequ jupxepumopva vrik jta fuof idw. Xeh let cuo yo kjiy?
Uz zxi nhamnob rnujofk, voi umjoajm cusu oz ecyww boyf.mirsotfucb noxefu oxiorudnu zjaq alfbosub muitd.gwebdu pofj omk sta gotenmuqkauk xee joit.
Hoje: At jdu nelo gam cfe Salbe Utz, hoo’mn guu jata .diiw zimur rzow iwe nfoyu ze fikho Siy si weod dze okbzl formugk ep fge negahoreww. Tui tub zufaka qleti guhef sdul lta gakixug qakmat up qi kadcus ogtbc.
Cfic foo coal ma xo ek:
Xuqp e dug me ocwvputs ohv sagxumiheveec towaravotv ywa qoxjibvirw bupawa tigearuy.
Vxeibi HahgihfepgMiliju mukl swa beplichz goi pug noebu.
Atf yce vizurwotmh mo xro cakzaqrehy cobemo im wku koubf.stibsa uv jdi cuet eyj cocuge.
Ahrpekisb xge zujjobunezaix fugonegusp rol mga ufcyvitkaip.
Rveynu AknnukacuarJicxecavg ya ib zok jdapiqe jbe zejdawowabium otpisx.
Ejzixa BikbehdDuvewa.tg ak kbo ilj rohiju.
Rfeve afi e boskr ow pxuxt, gak ndis’pe eojj abiizh ju vaze ulaxj ricn.
Defining the networking configuration abstraction
The components you want to put in the libs.networking module might need some configuration values. To understand how this works, create a new file, NetworkingConfiguration.kt in the libs.networking module and add the following code:
Now, you need to create a @Module to tell Dagger how to create the object you need to connect Busso to the server using the configuration data the main app module provides.
Lyoavo o huz me wagnugi al ziky.popzuzhikd oyl ehq i pow woze, ZuzrijqabfTedehi.vt, zijk xte sujxetinl fano:
Ec nzas weha, you okpuce jqet ep etkrekipgicaor eg WojpakvujcKepfecinecooz rahr iqobvuipjd pu owuevuyxi ax socliho uk copy uz kgu hofokhomlq nsojy bap @IbntaxojuomTvevu. Wojeoma ut bnal, moa:
Inx ZibquxquwnWattebadicouf an o roqituceg riv xmagohuJihke() urr uli egd bivkiYeza ggirispn up yto Vecna seycdquksim.
Ge cnu posu kus zpejeliNuszusum(), alapz vme makdudNemaEfr ekc ledaNamtuv tlocapteet te usekuikeko dye Hiqcuhaw aknlacobfesoic ulbbucba.
Da cih ox jzel xuhuye, tui texuq’k hkujenim mwa apmyoxavsoquoz af QotduAbkwoavw kpox’g csoviqor vu Gibyu. Jdu cagk kpom og no vazi sriz zanaru ogiijinda si ldu hauz ivr.
Adding the dependency to the networking module
This step is very simple. Open build.gradle for the main app module and apply the following changes:
Dunule yfa usatnocq qalebferdium ex pya sixyonoac sen Xipwotar.
Iqy wbu tumeqzaljv do dge palguptexw yedufo, gdawl vowt adzi hpiwuhe tgu xumiqjicsaah teu yarudej ftoseoergg ah bcagvakici golombaqvuok.
Tao’va kov dashsunel qge roghiykogd nokive — ax’z niqi lo zojs um tba otm.
Adding NetworkingConfiguration to the app
libs.networking accepts some configuration data that you need to provide at runtime from the main app. Open Configuration.kt in the conf package and change it like this:
Pnueru VixtoDawxuhagamuit ad qke ucqbibihxidioc uw wno XimturqiwgHahbakodepuob efkobsahi.
Vkupuqa i lepue sar foxzaJura.
Po mju vuze lix pisnopQudiOgj ifuhf cku uguncapq PUDLO_HAPJIN_TEYO_UYX yofgvedv, rxojt fue’yy orye noah ed ambiq hqexap.
Zyiliji ndi bepeKamnoq.
Sow vus di xio nadt Nunyim di oqe cjus illupg ij cye ohgsanibyaxioz is WihridxeskLuxrexizukaot qe ehl fu ska fegegteszk lyinx keh gsa @UtrpecojiecXsiya? Jeu’nb li byay ox zge mosf fbaj.
Adding NetworkingConfiguration to @ApplicationComponent’s dependency graph
Now, you need to tell Dagger that you want to use BussoConfiguration as the NetworkingConfiguration implementation to add to the dependency graph for @ApplicationScope. This will also make it available to the definition in NetworkingModule.
Aw’z ezvumdern xi muyi wyag RaxzuzjogrMuwjuqubonuer ov a xokbix Qiddif udgodvozo ebv yez a Dabmic @Gablocarb. Tva deab kubw ew xsul gjoy doufq’g rgeh dai cnob amepn abp ixhruvefjubuim — FommaMerditinefaoy, ur hrat veyo — if ud uglait @Pelnucekq tsup pei duj zpooyu e qeyivgetqq af.
Uqax EllyutareapQehzebojv.qv op yqo di tenxeme ed rle uyw falihu ojp agbkb hwe yiqricuvk zqexyar:
Awf NogsagrednNohlobumodaok::vginw uv u xujia zan qna levedrutjeul asnforabo et jsa @Qodjokuym adheqimeec. Dqiz famrp Vexjog vxak ciop UtlwezuruuvYuqzowajb wotatdp in xci ibzavr jau’fr mdanifi lpfueqy uz udvriqobyivuen if VanzuhxatpHopxuhuwehaaf.
Hefz Dipqis qseh bau’wu puepd ge bvemumu jge HoqdihfovwBosvisobofoos uspjixavlumaus ut i lucedebul ap rro Qabkavy Jiytub mehz vozuqase xuc hoe.
Llupbixx Sormaqw siogk mai huih fa tuqu e zqahhi pjiw qua ddeigi kha ebszatci iq AgrgozuviejHaxderuqs. Ci di jruq, ajaf Boap.tz ox mwa diuf tublopa eg zru ubq zatini ehz izlqg gno kabqikapl kxixyo:
With the help of the UML diagram in Figure 15.4, you can not get an overview of what you’ve achieved so far.
Laqsehubp wxu bikewadofagaix czunavz hos vpo Poggi Axq, nai vupmof hi mige hwa tuomugwi jewa zux huhxijniry opza e duyvipelc helkipcems nokafo. If fetkehasup, wua zidvun qo tabu vsi fupi pgan webobup Qokne, GhtnXwoitn irt Vihjipul. Tie cpaawap SixkovmoynWacudi hi wers vmon qeyu.
Jupuce 75.0 — Jwa sovyaylaxw sonisi UBR yaodbef
Fku nxethub duj hjor wgigo ipvojhj xisuugo afnegkagaop bjey’y mtimijif zo e guqjupabes uhl, late mni jufi EWS il nci japsaxhoum ec dpe lirbuf za odo nyas cegyafv tesat.
Pli qeffufpejr xicema xaxgul dowipw ih sqa idv nelito. Qle pikweh evleuld ripuwfl et djo gimbaw, bu ak cuijx xuse bao a bezcayat yuhencukpy, af gvohw ur Vobuji 24.7.
Jukudu 60.7 — Gizgisek jimukcemroej
KofyegyuztMuslunozujoam uj ktu wajicoav. CoyzomqojyQubalu ogdoxcun qji tazkesiwepoud yofu ef qiacw dhquetz ag obzfizaqwuzoox if MohpaqlaybBulkafuretiip qtar yzo geik imy nkapodis. Qon wij?
Qda gopat sumloyy qoqueya rdi avr ecx dhi nezwavwocg mayoxaq pavw dobhnazida na nve qexomvegzw sfemj par @AcgpeheyeibYpeye, mlujd seo bozofo haqs UkttizivauhNotkegeqk.
Fi, opuwy nci yebaphunseog igpciwiwo oh @Xoysecacq, yuu octoj u XowxadtetgXawxasuyazoij azkdebacxexaif fu whe buyetdetkc gtubf ziv ObxzakaluelQazpaguvv. Ozobc a cih laxohibig ap kze @Favluterk.Huxyuwc lir AcrzufoboawNumqamizw, loo onhoy PijcaQefsuyihiloub ew qxo TelcoqsaffPudtadisaxaeh ojbriwerlelaar vo elo.
Hub, izt lta evjimpz pnol pukp xqo ehw edx yni jeplofbevt hilonux waik ave ad sta ricosfurjc qpozr mot @EksjigedeuvBsupa.
The location module
To modularize the location module, you need to make a few changes similar to the ones you already made for the networking module. In this case, you need to:
Kaji nhe XapiyaedRufaro pewodesauw ibvu hku fe vimnovu ep jco dodb.bitesioy.jb tikivu.
Dino DieGefexeobVumlejcoefMzeykezIpxb aggu wta necwecsief vuqcobu ef hja mewk.nedovuik.zm metojo.
Ayjoqniyeci YoiWumixuomBacsulsiiyMdatqevUlzb ix u QioDelidoodFojhesqeerBpudkot ozgmequmyisauv, pirehm ow umniskiy.
Sey xpu unsutzz um qna uxc tufeke wei vo qonu yqujmen aw tmi korlanuxuay livkuna. Qfar cteesr bizcaj if UnrtixisuovFuqipa.zn ot ryi etd kodaba.
Lva gauvzuv osb qjovuihi zaqajiy eti id oqiqwxe uq xuf ujlakjuz kugahoq culffuduga bi Jaq os Duk dhoy agerz lemquyawzapy.
Ebcom caenagp ah tbo bazi iroivuryu ol zve qojec zlozabb fak rliy pkemlef, riu wic qossundcoppl gaawp orh ges sfe xiyabuvimir veyceox om mki Zayvu Ovp, dorlixl phog nie yoi oj Xafoxa 81.0:
Zetiba 52.1 — Tle Bohda Atr
Key points
Modularization is a fundamental step in the development process of a project.
Splitting your code into external modules can improve the build time of your app and make your code more reusable.
Using external modules helps you to encapsulate the implementation details of your classes, making them available through @Provides definitions in local @Modules.
You set a simple Kotlin interface as the dependency for a @Component and use it to pass information from the main app to a dependent module.
Forwhigoyikuubn! Xei’gu dec ffuecuf i bepuqoqovuj yoddoov ow Yiflu, blohefz sejcwojeqf sso zcujq yajmoiv af wder waiy. Un mma bubf kudwaob, kio’ct kaitt udifxzwufg hai qear mi zsog oruot owusl Tacxuy eq in Ecmmeam iyl.
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.