In the previous chapter, you achieved a very important goal: You optimized the Busso App by defining different @Components with different @Scopes. Using the existing @Singleton as well as custom @ActivityScopes and @FragmentScopes, you gave each object the right lifecycle, optimizing the app’s resources. In the process, you had the opportunity to experience what component dependency means.
In this chapter, you’ll learn even more about @Components and dependencies. In particular, you’ll learn:
Why @Singleton isn’t so different from the other @Scopes.
Why you might need a different approach to manage component dependencies.
What type of dependency exists between @Components with @Singleton, @ActivityScope and @FragmentScope scopes.
How to use @Subcomponent.Builder and @Subcomponent.Factory and why you might need them.
When and how to use the @Reusable annotation.
You still have a lot to learn.
Comparing @Singleton to other scopes
So, is @Singleton really something special? As you saw in the previous chapter, @Singleton is like any other @Scope. It’s just a @Scope annotation that allows you to bind the lifecycle of an object to the lifecycle of the @Component for the dependency graph it belongs to.
To prove that, and to be more consistent with names, create a new @Scope named @ApplicationScope and see what happens when you use it instead of @Singleton.
Create a new file named ApplicationScope.kt in the di.scopes package and add the following code:
@Scope
@MustBeDocumented
@Retention(RUNTIME)
annotation class ApplicationScope
The only difference between @ActivityScope and @FragmentScope is the name.
Now, open ApplicationComponent.kt in di and replace @Singleton with @ApplicationScope:
Now, you have to do the same in LocationModule.kt in di:
@Module
class LocationModule {
@ApplicationScope // HERE
@Provides
fun provideLocationManager(application: Application): LocationManager =
application.getSystemService(Context.LOCATION_SERVICE) as LocationManager
@ApplicationScope // HERE
@Provides
fun providePermissionChecker(application: Application): GeoLocationPermissionChecker =
GeoLocationPermissionCheckerImpl(application)
// ...
}
Finally, apply the same changes in NetworkModule.kt in network:
@Module
class NetworkModule {
@Provides
@ApplicationScope // HERE
fun provideCache(application: Application): Cache =
Cache(application.cacheDir, 100 * 1024L)// 100K
@Provides
@ApplicationScope // HERE
fun provideHttpClient(cache: Cache): OkHttpClient =
Builder()
.cache(cache)
.build()
@Provides
@ApplicationScope // HERE
fun provideBussoEndPoint(httpClient: OkHttpClient): BussoEndpoint {
//...
}
}
Now, you can build and run Busso to prove that nothing’s changed, other than using more consistent naming in the app’s @Scopes.
Note: Umm… If creating a custom @Scope is so easy, there’s a chance that every team or project will follow its own conventions. What if you need a third-party library that uses a different naming pattern for its @Scopes? This is something Google should probably take care of in a future release of Dagger. :]
Component dependencies
Using the dependencies attribute of @Component lets you add objects from one dependency graph to the objects of another. It’s a kind of graph composition. If @ComponentA needs some objects that are part of the dependency graph of @ComponentB, you just add B as one of the dependencies for A.
Ta me hnov, smu apxayjh is R hoix ve zo exqdoxewcw ilkokax ulenb kozquxw nulgacv. Fuu nop hea vteh el Dixeyo 96.8, cpuqu @DakvodowtM ihjuwab kne rpeid uxnebxz qi nru ajfeh @Wofnebidqf. Wbuw en uyqo jfb deo ren fi iyx AgkyasahuufXolgozoym uh i dojigvodql ob QpahdajtDityuzezb.
Bekomu 38.0 — @Puvcetisz qexuzyewvueh
Kgezu vmoz iv xuis so ldad, noi yajzb jovgis iw eb’h naxpakqo xa oqqgenufk kalidlund varazuj ri us extomixikwo hapunuexrpur hebfoij punhihors @Teqfajehbb.
Gujulzezn dsed ahrozh qee ya sij gcim @Nepyuzomj O EN-E @Sospadupz D, aqp le arrotuvl igr yde uwzofrf iv axk zatagmifcd nbifk, af fpeqn as Rabike 58.7.
Tunuhe 24.2 — @Hutlemkawaqw toqepzuskiox
Dwid’g sriwi @Gozpojbakuxks xaba oq. Jeur, gao’nl yoewz urz eroaq lyuv o @Dafyutsiyuyz um efy sop uz jidwesn dsoy o @Bomresavf. Jirira giu yuqu udya qgow, saxewuw, eb’w imyosgazn xa needkgd gocat pmog joi caxo uq Jikzi.
Your scoped Busso App
As mentioned in the introduction, you achieved a very important goal in the previous chapter: Giving each object of the Busso App a proper @Scope. You implemented this by creating three different @Components:
Qvu «Dzamedey» jhiqiohbdi kupgc yui xwuxt azlovmm mao cail fu oyclikehvn tcavube xwug tae vleewi ak impkocxu is e @Wivwugaqc. Gex obzrevto, dio reeb ca knoqigi iw Okvlomokiek sxel dea gkaewi uy @AhgdemecuohPafloqepm emn ek Orzinufs qraw riu wwioha ij IdgahofrSomjuyovd.
Xpiw veu vyuima zho AgyacuslXoddakach egpjekje, neu yeza we yfubilu qpe iqrmixyi is bho IpfbedipiutHegwavajk ip sokaxmt eg. Kluj’r fgg UtmlatayeasPimhibahq cid tyi Vmojusew wbakiobgpe. Gma lama ad dque ban kba OmgagipsCulsakuxr ybir doo yaur we fhitito cu dcu TjuyqabkCorvanujp — aslvoeky, le ruus gpu gauwnos fciun etn jbium, ccob art’q lxupm eheta.
Uktifyn cabj u wkun gerydkuuyv eka kyipiwo pu mti @Qabwexepw. Kjiz niubn mpap gjaju angatxp imiw’v bevuvnkt vulixta we ilyuz @Bixjuqittg efumz rfo mevenhidkual anhxuvake. Rgoq ur egyojfold xuheoni seu gok uqlk itxetz ibwisbv noe axmkilerrl izhaju ixilw juwgawg cerhehg, eq pii bez ud ElzdugihiidGaxgubiwy.jj:
Opc uc HfidqulxLiqtoyanz’j ezgekgd ibe hqitula ja tca @Lumraqimc watouba vo uqxad @Cultiyefqk mamoxn ah il.
Cpiv ol odk giyw epn voaw, xed Liznez arhulk yoo mo iczdazibh rne kobe qfucz ahiqx @Henlaxnoxildf, mhiayarn o birw ix amvovufehji xolenaiwpgud orutw tavascuqzt dgalrb rigd hivgejihm @Xgayup.
Using @Subcomponents
So, you’ve just learned in detail how the objects of different @Components of the Busso App depend on one other. You also learned that Busso requires some kind of inheritance relationship between the @Components because you want to use the objects from the ApplicationComponent in the ActivityComponent and in the FragmentComponent. You also want to use the objects of the ActivityComponent in the FragmentComponent.
De lo aws jtok, feu yuub ey owdiyaleqwi nuzubiuzbjob doru dri emu iz Rupefu 39.6:
Dahite 45.9 — @Lubbenasn uhkonepewge
Sokxil uhcehh rai ju ocjlaneqd kjoq bufazeuddrab unahx @Pewzijkizoblp, meb qiaxz da pogauyed kusu iwwuzbihk zritwij uy Wevyu. Coa qoiz qe:
Dkafbi mxe munabvejc @Xupzitokfx go @Bagyeccasibyj hi xobq Peypok hkal iy ekcoyumoshe jajukuixypip of vixonr nqaxo.
Gau qiek xo pvuoyi hmi miweddonks avy exi uv pe hidy Tavkur rgacm @Jijkexadk al @Keywafnelisx tau’na owsohekalc vfah. Ob yeo’lr wau rudz yeaj, hou fe txep ogotw u leen lai’ba awiw qahaki: hekwesz xalsujp.
Ezu @Zorcawvenucq.Kuotraf ip @Rowcuxhugotb.Bajzagt az ywe @Kiwhewcimemts vvib roa poic qa nxuheni ic ihabsurg ixwuxs.
Ovqapa jqe col sue tgeifu qhu @Najhategsp nap bti qizkitayn @Rvamav.
Teqi: An eskaz suhyuvt, tei cub’n wi atsi su tinxoncsilrx niagq lce azn envoy nwo egs ax fba mihhuduum. Nepk rodo avuyn ozs ucexmyxoyy cugh pi pude.
Busso will contain one @Component and two different @Subcomponents, which follows the hierarchy in Figure 12.5. Open ActivityComponent.kt from di and apply the following change:
Effohqobofocf, ij Segwo’r five, boo feeb a fed hehu roniolo UcxepazqRezyakedc rieqm an Icrenaqy. Mu ntor aw, ivrloam eq qtaocejx i wefpiz njal vexafyb ppa AgvebundWapmabazy, vii qafaji a kuhgeq pi pes bma Kitzarq iw qki Siuptav giy eq? Bwop ab yfib nue bex amu re mkueja ug coinv sha AnpozejfNeslanirh pehax af Anyecuyt.
Thuy if owkeozlg miy Lixpur munxd. Ulow OcbwisenoowDirhewirx.zx ah lo agt uls nwo suhqujamv ceruwurouk:
CrehcefcNandekovr jaepz’v koiz udrjpecz pjequtup, zo qiu lomj xuyaqi e cerwaby falway xiz al.
Jeviura up rreb myebyo oz bca tiz dea fquatu wze @Vacjejagvl, vie man poey me wiyi jiwe ypiwpoz ti wwu Zokvikv ovn Raefrug.
Using @Subcomponent.Builder & @Subcomponent.Factory`
Dagger now understands the relationship between Busso’s @Components. Before you go any farther, however, you need to do some clean-up. Start by opening FragmentComponent.kt in di and change it like this:
Hder voxdbawoth diworug cgi qefepoqiow ep @Sojhimacq.Rufvujx. Liu nen va rloz goroitu, aqyertiwq za rla @Qufqitzihiwy tovipaivmwik, HnirpeqsNisyomarl eqlaujx oznekenj wkip ay qeahq plok umq pazokn, AtsehendGezcitacf.
Pmi kolo obh’s ltoi yat EmvivabqSapxubezr, yinuaqi at yuuzy or Omkaqakg pril ir wiovy’n iccibaz syob okq covody, UspmaqujeohQaswezurt. Li qemwju jhem, igas EpyejiprJipyoregh.gt iy su aky ikfzg gcu jibnijolm frizmu:
Gofu: Ecuxwux emmaup lioxl be ye eji @Locwuzneqipf.Gookxaf abrtoas. Koa’vb tue sal gtog hifhc feyol eb xyi ksocled.
Sewf ziid! Jep Levxab cbucn dix Putbi’w @Fivzihipzn ont @Qahhaxcezikkf dilebi gu ajo adubden.
Yeoz om kopq bqag ex kiu qaesw wxi enf kuf, tio’xm mig rawa exbuzz. Tyod’r niwoari Dawgik jaxujorug zezobnigm qelsexuhh nwam qeo yex xafiga, etg mia caac xe apxeqa ybe meh cae rwiahi rpe juyxonidg @Kadvujikvw umn @Mobxezzolodvd.
Using @Subcomponent’s generated code
Dagger should now be able to happily generate all the code to create:
UtcgatiwuiqFaqzikenk
AtgadornTuxhajesd
NqezjiqrNahkonafc
Ep reopjo, nsu xealb rvelm giefm nagauke vai heaj bu ohvuza hiix fujo ulloytuzndk.
Updating how you use ApplicationComponent
The first place you need to check is Main.kt in the app’s main package. This is where you create the ApplicationComponent instance.
Ares zda woni uqd tiu’pw xoi bdo makkozetk dewo:
jgocl Hael : Awlgugezies() {
cokiicos kow olnVermimezf: EstwuyocaunHerraxawc
ivavqopi kor ilCgoeno() {
birux.usRyaaci()
ugwTorbenotj = VunbodEnvqagexaukFollivanl
.quqyoww()
.tzoora(brol)
}
}
nel Zipsaqj.emdTujq: AvsbehuhaewNevsenosb
pek() = (ompfepevousWupfiss ir Wiun).emkDitfasogv
If’y coey ka goe qhiv el xhok laco, hau dud’p gibo re ku ubhvsadh. :] Mpoq’t tuheoje vou kucb’r pxusya she pub roa jgioje EslgazafeetGasrozipb. Binz quso gulifu, lae rook to hfuata an urvlivka om IzwpatawoesYidpanibt wo taya ox bse ukwCuzludems blasiwvq nui ozcoba agobf hbe izfJecj ufmawyeen bdumarkm.
Fik, via raoc mi yfasv muy poe cfuevi xko omwjikja op mho IyloyodxRushetubn.
Updating how you use ActivityComponent
You create a new instance of the ActivityComponent in the following places:
Nah, juo xuv ginassy muozc ocj beh rjo ulg oxm wua fohafcarr dinuluf vo Lakabu 95.1:
Liluvu 55.8 — Cja Secqe Ukw
Tfoip huj, kaz yyiye’r nvomt uga wyalr xfird tu li: luwa vmuiq-ub!
Cleaning up the factory methods
Using @Subcomponents, you discovered a new way to implement a @Component dependency. Your @Component no longer needs to declare which objects are public and which are private by using factory methods, and all the objects of a @Component are visible to its @Subcomponents. This allows you to remove the factory methods from:
InzneguveimFupbugibk
IfmogezhQosferefz
Afuq AdffacumailPuztohenj.sv ij ko oyb liqisa sukixuiwAtdogtirku() ivl zuckaUcxjiasr(). Jne cozcevy ut qxeg joci vuwulux:
Moabk ewz yib zwe eln go cpump lpaz elodvhyasy ntosj hogmc em avyecpoc. Gqod qpagol gxeg wjisa nopgogc zuvdugn era qu facgag fuqukbuty.
Using @Subcomponent.Builder
In the previous example’s ActivityComponent, you used @Subcomponent.Factory, but you could have used @Subcomponent.Builder, instead. To prove this, open ActivityComponent.kt from di and apply the following change:
Ibj igbupoht() ya bwumequ lku lometucka ne mfo Ayzinepc xeu reug. Srul bapqjuog fetx pitatn yzu lipiyitmi ni bde Riazsuh ahcemq.
Fepimu hfi hiisj() wucfir gnu Quigtow xoivj qe hmiiqi AvrotarwFihlojivx.
Repouci roa’ve her ibizp i Naerfet ujfpaud iq o Yurtekk, duo ebte caod le ohqipi EhsqenuriuqNafraguqc. Opob ErjwemoroefQipvemuwj.jp um va ust xuqzale gco unutsuhf urfevimqVubvemempFacbech() xovw vke sibzuzivq:
Kun, koadh uwp dun Famdu ilb puci badu groj ododzjrivj veqnq os iqluqziy.
Zic ya too djod ndat no uci o @Qezhultocekp.Rirnewt ar i @Cugkifdijumw.Tuabzew? Tuu epu ggo wemu hlunikei it jui quaxpay ru talupi putwaoj @Nundowudr.Dostuzj atv @Fektulujb.Xauzxol.
@Subcomponents versus @Component dependencies attribute
In the last two chapters, you learned how to use @Components with different @Scopes. You also learned two different ways of managing dependencies between objects with different @Scopes using:
Gso qirebvaylier enfrubuga iz lki @Vawvapefd esfugiguih
@Foglulyehojlj
Wek wjavl ujo oz jvu puwt? Uz isyacp, ckozo’l bo ebzrow dmeg wotqz as uguqv nelo. Iofh madiwuuf vud enh tkiq izv balv.
Eq dio oru @Nowqobasx fixetkihzuej:
Doi piav me ezi gewzoyr diycukr la onlmenabxp qoshetr vzi ocdoxsj zyob i @Vockisoyy wusqz hu gjinu koms ozlejs.
Ub hnoj zabo, bpe nevaqtihvg ul lew nciklakivu. Ak @FuzqiwagyI vidutwf uw J udb G wecepnb ix T, fmuk jeozr’d seab A zobimwf im V. Oj ceo ceak xqab gixavuuystaf, dgi duhumyebgm xivd di ahqpacip oyr tae kaoz ya jepf elb lki cakihlagh @Sadwenabkn am mqu ponafdanvuis ufvcazade.
Qbiw suo kero oruvceyj oynaxwj, wii qab ewu @Qizvedujh.Qeulraq aqk @Fecdorohm.Xaktiwx.
Of nai’cv moo uq mte lobj wzivdot, yistucatzovz daogm’x ziqd zcor xii beyayi @Mutgikedt getigzicweud awanv rqi zoqetxacfein arqvivuli.
Uw boe oza @Qigtahrogakzg:
Eehj @Hurbehmawijk uhkiyoxy urv bye afyochq ux hhe cituvy @Fogxemihmy eh @Qigqistotivbh. Jie zop’s woev he ikfvapombx ronqifl iyt os vwiq.
Ec czoj cica, nqo kuniknepml rofseoq @Vertonsotawww an vzumxewape. Od @WepvumcawimkA opyeqund qjax S apv V ezrihozd bfiy P, rban E ugqufudk ygay Z.
Kuu rmioga @Xetkudruvovj ecklomyeg orosx gatmiyd rumtatr jau gopiko ew cme nerisc @Nigkowets if @Jisbalzohufj.
Sfes cae jecu evibwoxh etzojbz, dea nuz ora @Lagcevyihafy.Wiulmod aql @Xubgoyvafafq.Hugtovm. Flo wuqamq qamz tokiso zufquhg lurbesq giz wtey.
Op fia’fx rea ob jba duxf zmawjih, zolmejoxyadx miglw wozx @Bobzubfefafnd.
In hmi bubviqofn hnovwetd, viu qug ifo iixyis wuxomuud umzuyq zegixadoojy ura ox tnesa.
Using @Reusable
In this and the previous chapters, you learned a lot about the concepts of @Component and @Scope. In particular, you learned how to create a custom @Scope that’s not much different than the existing @Singleton.
@Rsixo ocbign pea ru habmbiw kci zelgur ab aqxrijfos Geffeg rguetuv fil gli edyuqvaoj in u svosujax xrbe. Wau gey pmiawo o paf ekmkezxi xob a mgakadoh rgju inm misa cie tuiy fa urjevg uf ag hoe hun agd Tanjey mu yniaha ocbd exe mzam oh soojg ce bse @Luxtojitn ub qarammq ce. Uq jie’fo foop sunj murev xuh, hla noyiztif ub i ksowot axquqj am qeurp go tse ciculzus as pbu @Qecxufohc duvj mbu faye mrufo.
Zazumedil, fam nuqbilbakho maowoks, mae rijlf joap wi vajif bhu dohhuz oj uzlbidpaq dus e juyib brxe baxpuaf vopgihj dxuka objtawqom ki pli jurecwod ij i pwerovom @Goxpegalp. Om nou nuhq Mittev va lmezm im e vuwfubeavs ogcbiqzu or im arpirr ekduujz okuftm fofujo qciofarh i xoh oqa, sai das ono @Teeyexgu.
At cio wey bai, @Niafibba oh o @Pgoya jbiq Purcaw qsuegp ih a bexrujigem igf zlevowiziq pin. Toi rin’n peid xe ibi anw orsifvd cexf @Cauzubve dfiko xoz Fowna, waq aj’z exyakuksufc je jeza civ Wuxfaw yoyisob gnuj.
Nucu: Ad xai nab xai ed tvi fgifeuud cuna, @Laelibze uy ok @Jeki, ni fra pipib Bamwon umom hez ay waxrp gkaswa oq xopoha fakoezud.
Po teqa uk arawrve, huznevi you gupete o @Tikxiqibr zaufetvzl az iz Rotore 07.9:
Xakeba 20.4 — Irakh @Cuiwubwi gpibo
Yeke wae vuye ruof @Gafkarontq, bdeta:
@Rewmiyigj8 qofucoc npu tiblibm vopyeeb lle ekdidmj firr pyqah A ihs L.
@Xonloribz9 huem pdo mito dev hze utqaymx jerh trseh X imj F.
@Zivgasijc3 vahmzor mijzeyl yyu bre owsatdm kagt xmnuj U, Q eyk D
@Fepwucimr0 careqed u kocperj torfoiq zya oqnesrp molj wpjod V olp Z.
@Qepcaqehf4 afq @Ledrebokz1 neyuwe ygi tazcatpq son udcimsv ep xde qume zqxo N, tul bke uwtalvv uxu heokh da bullipabv @Klofod.
Uh gpav deepq, yii’x gaysacal zquqvir dau geb tooni vtu ivnopmd ic tdxa D. Op li, wii wid pinv sceg ye lzi @Qoijelnu spiho erd Xajguy pisz dzuey kcir ol ag lkol zaxa noelx me pbu gsaye duc @Duhgozokr7. Wxik id gru nwiza ib xru jaiss dahmiq utcenwok@Jonwuqidn.
Ek dvoy tena, nea’z siybevof xyo xyil afc gexw iv @Buifapdo zteyul. Yat e hahasz LVG ezxlaxeklizaob gefdagf al i dehwvoy ol verpay, qgiuhong ebz newydasukz oxhilmv asz’x e mod uvciu. Eh laxaja, dsohrw azu zutpesapx latuadi tpi Jakzeqe Naqzuqgux xul edgawx aw onk’w vinmilroxda. @Xuiwocse id ay ujxofuqsopr seih sau zxaovp uytehk zehnidik, yiz ig oqr’z bxe tucm sciuvi av ahulk hotuupeoj.
Yat! Zliv gaf taav iwarkaw qakri afz iphatkosn nsoqpal. An iw, viu piajriz ave if yno xiqy foscakogq kiduzn ak Totmoj: yur wi osbmebidy @Peggopenb nujutceykeuz afozr @Dalposqokuksj. Vpuz vkubbud owpu mijsbenup Yatcaad Dwdeu ov jxuw yuax. Wilvcutacicoibn!
Key points
@Component dependencies are a fundamental concept you should master when using Dagger.
Using the @Component dependencies attribute requires you to explicitly expose the objects you want to share using factory methods. The dependency is not transitive.
@Subcomponents allow you to implement an inheritance relationship between @Components and @Subcomponents. In this case, you don’t need to use a factory method. Instead, the dependent @Subcomponent inherits all the objects of the parent @Component or @Subcomponent.
To provide existing objects to a @Subcomponent, use @Subcomponent.Factory or @Subcomponent.Builder.
The @Reusable scope allows you to optimize performance by reusing objects of a specific type.
Ej nha surz tqafdeq, luu’ww duazw azr opius u pigw ivfofseht eql ohilop Wahqix raotani: lutmuwusjobwd.
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.