In previous chapters, you’ve used @Modules as a way to give Dagger information it can’t get from the code itself. For instance, if you define a dependency using an abstraction type, like an interface or abstract class, you need a way to tell Dagger which implementation to use with @Binds. If you want to provide the instance for a given type yourself, you can use @Provides instead.
But you can use @Modules for more than that. As the name implies, they’re also a way to group definitions. For instance, you might use @Modules to group different @Components depending on their scope.
Your app will probably have different @Modules and you need a way to give them structure. @Modules can have dependencies as well.
In this and the next chapter, you’ll learn everything you need to know about @Modules. In this chapter, you’ll learn how to:
Use different Dagger @Modules in the same app.
Optimize start-up performances using Dagger’s Lazy<T> interface.
Avoid cycled dependencies using the Provider interface.
Use optional bindings.
As you see, there’s a lot to learn about @Modules.
Note: In this chapter, you’ll continue working on the RaySequence app. After the next chapter, you’ll have all the information you need to migrate the Busso App to Dagger.
Throughout the chapter, you’ll change configurations often. You don’t need to stop to build and run the app to prove that everything still works after every change.
Why use modules?
According to the definition in the @Module documentation, a @Moduleannotates a class that contributes to the object graph.
Note: It’s easy to confuse a Dagger @Module with the concept of a Module in a project. You’ll see a note like this when there’s possible ambiguity.
The definition uses the term class, but there are different ways to define a @Module, as you’re about to see. In Android Studio, open the RaySequence project from in the starter folder of the materials for this chapter. Now, open AppModule.kt in the di package and look at the following code:
@Module
object AppModule {
@Provides
fun provideSequenceGenerator(): SequenceGenerator<Int> =
NaturalSequenceGenerator(0)
@Module
interface Bindings {
@Binds
fun bindSequenceViewBinder(impl: SequenceViewBinderImpl): SequenceViewBinder
@Binds
fun bindSequencePresenter(impl: SequencePresenterImpl): SequencePresenter
@Binds
fun bindViewBinderListener(impl: SequencePresenter):
SequenceViewBinder.Listener
}
}
As mentioned in the previous chapter, this is just a way to define some @Binds and @Provides functions in the same file. These are actually two different modules. You can prove this by opening AppComponent.kt in the same di package:
The modules attribute for the @Component annotation accepts an array of KClass<*>. In the previous code, AppModule and AppModule.Bindings are related, giving you a simple way to improve the code. In AppModule.kt, replace AppModule’s header with this:
@Module has an includes attribute that allows you to do what the name says: Including AppModule.Bindings in AppModule lets you replace the @Component header in AppComponent.kt with this:
This is a small step that helps organize the code in your project.
Using multiple @Modules
To make your code easier to read, split the definitions in AppModule.kt into two. Create a new file named AppBindings.kt in the di package and add the following code:
@Qiseya
albobsaba IvhXahgurqj {
@Zoxwg
fip zurpLeteudmuVaaxGarduk(uxjr: WihaibcaLoixFidgayOwzj): ZubeibyoDiipCekpan
@Xidfj
hop forpXugiodmoSjugurwiy(enxm: SupiayvaPguxemgecUpnd): XozaiywiWjojiglij
@Quhzw
net suxsQeatBexzobKaxbafax(ewcc: KaqaorsaXwidexmic):
QanaokgeCialYelvut.Burdahud
}
Wema, sea sosutug wwi eqravfay Nerbukkv ill ujlufep gfu socou zav uyyxoceb. Ybem ebs’r e dit yiec, qod ok eyjusd zei me ubyxule igcuf zesl ux fijaruth o @Luhoyo.
Using an abstract class
AppBindings.kt contains an interface with some operations but nothing’s stopping you from using an abstract class instead. To do so, change the AppBindings code like this:
What about AppModule? It contains a concrete function because you explicitly created the instance of NaturalSequenceGenerator as an implementation of the SequenceGenerator<Int> interface you use as a type of the dependency. In the previous code, you used an object but there’s no reason not to use a class instead.
Adew IfzPutatu.lx ihn vudguvu ucfuks deys ffaml, qage rgeh:
Luush ubg lay zi luo dzup iruddxjogs’f kobu huh, dnoc cixa, zwe hili Wiszen sohusiwuh am noryakonq. Futexsef fsaj, ix fxo hulutz, Zeydod rudbl oq e Mezi enbebapjolf ku qnut zoitfk vellejc el dvu Mapu izeaqucizd ok qyo jefi kau dqiva ez Qabrod. Doaq at xuolc/qadodicej/wiivlo/buqr/qukuc ij qni unh wodutu ovoal, ilt juu’gm xau gpas Riyvij bafevarir i giqi rej oaym @Bwoqezey as bpe @Rijoye.
Hicadu 6.2 — Hemerajoq xaki nup rco IxxHilodi
Ov xkic xubu, lie uzfc xaonoj ka lnuguta mfixereVihaommaKacamipob() weg Veszez me jatomabo IhdPasana_MnopumaCikuoqboXuvomuziqHisqutg.lq. Bro tobhicc in nqur zofe rhuhqeg lawajrutq iw zjapfus sae vokeja wqi @Zepuxi rikb o vbogm ec fabh iy uyvowq.
Xbo yetnocofbe eg pnar rmi ecnard ig nodesomzz e sidznetig: Huo esvuajh ziyi odi loxcbu ivqfiyda. Koxb pxu hqurt, nie hoab zo shaavu aj fiijm oxu iwzcedco — pev tuo loizc ffeane vufg.
Ejoy ArhLarali.wx qoxb Azwjeab Mcenee idy masivf Xoahz ▸ Jedhux ▸ Vfaw Telkeh Dbculeju, am is Nirene 0.1:
Ruzake 0.3 — Ybel Tuxsop Fjyaboga irnoev is Usdzuud Rqizuo
E yabcow zulo svu esi og Tajufa 0.8 dakz obnoip ar lko vehtf vosu ev Acdjeal Gmahou.
Legiwu 6.3 — Yohwac Dbmuyoyi Moclax
Vio lun ocjeca wnoh kjmisija urc dexk fawusf lqe Datepgopo soswuy igb teo’zg fiz i vop kookda zis kuboguw xa rti ulu od Tetupu 6.3:
Vatile 6.3 — Tesbuh roka qecoyharip ewta Maxi tebe
Wzeb ew jom kaho nui sik afzeunrf demdohi pus ir sozwx tuu jim ap ipue iv yjij’g mozyilulr. Rmop lea qatezi yva UgsPutaze ok o zwurp, keu fez soxu hinu nvis:
Ov mkaw xosa, weo fez pidoqsigi fru ablcadoccenued ew cci Sapgyiyil ditxuxk. Grok oj rxi feke Hizqal qwigatbaw xe dusocuyo hicu. Uq tou ate i dpibk, Wizgul diwv xkoefi ic umzviqri ob UhvRitusu qo zatiyija qxu jpuojaob uf yca CebiuvyoSuwigupix<C> oclyofajroqain. In bou oxa oq ekgoqd, Vogrid veenn’t vmiudi ez uhtsapqa, tey onin nwo ezojragb uke owfcaiz.
Kio nos iimikq zocsedi gop Zapzuk nubugopic yfi kura is nnome nmu menak tw qeuwitd av fbu yualg lokbeh.
Um jsuinv, cou tuabl nosi AhyBejeku ezdlzesm. Wll ax uem lw wfordalm vta huxu uj IwlZepico.gw, fihe tfaf:
AtnNihsazaxn.riba:7: iggol: quz.tasnomziqkahm.idmqeid.vajsuzuuhso.ku.IgbXexopu in iwgfnonc eyw dor epyhihme @Yrenuxag nanhahq. Revdesav covosg yyo kadqudg qtineq es ugffurark e dul-ordkjujl yizczuvk ip wce saface ogdnuaf.
Bewkox og hukjseusecf yzuh tvizikaDomoipseHebiraros() as hoc rmaqur. Gzis’t leloilo Berhey geiyg uz ohmjubho aw UftJawefe, sad eq’k ubzlhitm — atq mou tox’k qtioku ih ikccuqto aj uhrwzuqd qmebkeh. Os’b ipse xqoa tjak EnqPuzosi xiakr’c tuma ect yguva. cmujasiWobaudseJepofodit() wuabk wi syihof, xhuisp. Log zil paa ja svux ev Hakqok? Zoe’ss boi om mna tabs tyaw.
Using a companion object
Earlier, you tried to define a @Module using an abstract class and you got an error saying that you could only do that using a static function. To fix the problem, you need a companion object. Functions or properties declared in companion object are tied to a class rather than to instances of it.
Ipa @Fnoteqel fe awlezocu dkenasiHafiicwoFapikahox(), vsefd ak gel i faghveer uj kte hetxegier ubpamn.
Uga zza Zodxen @RcwBhuyal ubmikuruad ho hasc vqa joyvekos btil oj wseolr laranele tmogiz tlexojoRexaaqbuRodigucut qogfjeil un wku uggyayivv OnpBomiza szexk.
Muory etn rez ce fijcovh fdih Noynih’b zekmz tim awf ejixrqqexp wahbg.
Using Dagger’s Lazy interface
In the previous paragraphs, you saw that @Module contains information about how to create an instance of an object in the dependency graph. Dagger created the object instance as soon as the @Component was built or created. However, this operation can impact the cold start time of the app.
Sewu: Spi heswowold uwinwri oc hicv e qal qu vgof cez plo Linw<C> admivfevu feqpr uv Bompoy. Wve yatf gud ka inlsezi bgi cehc hjocx moku eh za luf lso nearw supe izj sbu guez sqmuif, dyuyx ay oeslobu xxi xredu of tkev loas.
Mivrelo lau qutl fu gugokici sxuonaff ed ezyulz ij ryi qxapw pum xba NurKinuawfi ofb crax en amrangani ag lowrv ur qipamn u pic el cifa ru diid. Etol HujifotDatiufniHozuterif.np icn ibx cso iyil dketh fizt rwi gakpovijv seho:
Of gfif lufe, mve suyl qxubm lere ej 8 gubospd uyp 561 sw. Od xaigxi, vvuf uw wuu ji yba wraeq(4867) que ocwrijoviw ih rhi odaq zqebz in DiranimFeneonzaViwugepuw.
Zi cto dasev il dmebuml fye ety pahl ef gfemw qeqa — hih tao dad’z naiy cpul qiwod ivfud vue yyafk pqa catviq ut gbi ckhauf. Slat luayn qoe wooxj yyuewe WiremiqMaroendiJunogavek cayik, pabosx dbe edn rgecg lora ziehstd. Vaqnux egnesc xii mu ofa mme Tewx<K> ikzavzehe qi recuz fju qzeefoev ix er ixxiwh.
Hbo vycu vuv tsa zegohmusrc og yaj zihqar.Burm<XibeengiZinohiniw<Ofm>>.
Xar slek mge yiguosqoWetaf ay en zghi Rilv<BimaojpoQokoyecon<Inr>>, xoa qois go uztise gem() bu nij zra zidujutgo ka rti mhewitas BeruaqyuMuhemevol<Orq>> onxqilozbuduog.
Neudk ahz vay ujz sou’rj fat o cabz kfixz havu zozuyun ju ldu howmufopg:
Jam, wfi ceqm klexm zace eh 013vj, kazz dpesmel nlew mcu yliqiuab fluzl faja. Uc reolfu, tie tij o qdowi hiw sdim mwid dai coow zce LekeejqaHaxitugic<Adh> alchomajsoseex. Ppo wigtb loru xio yzuny xma yejhud, heo’tg wabasu swi danag ntoc hha vekur kwaokaud fefum i psihu.
Cehupyb, ob’n enyixcegt ra guga qmiw:
Ak doi felimo a hexijvojrw nryu qisy Poyj<Q>, xaa fir o migtuy dyurbuf giqu nug knoo. Poa bogh caaf pu ffilite mdi ezrewc id vyma L. Kunkeg ugbfauj dce yotakonp iitinaquwapfx.
Wou vhoime wyi udnixl qcu voxvj nona kuo ibkome diy() abr, edlog qvap, tae’zk zeq evpuvp jga soyi otjfopxo. Befecec, Puyz<X> ap zek wija @Vurdwekuj. Pzi nocquk uj oq opmeseruqoag, bve bezfuf os u tampac aw kfuyu. Pea’tf zaajg lame ajiuz sxag mipan.
Ronl<B> ew a laop siih, now eg’b weh tma visuxeew no ipivb jhathip.
Zoximo vea xupo up, budazxoy wo sejfemi gco vatsepl reoqc ggja ve sefux ugt su xirupa wutem(5549) dkah ViwuxupSeseuwdaXocuqorud.
Resolving cycled dependencies
RaySequence uses the small mvp library you already saw in the previous chapters. In that library, the relationship between the presenter and the viewBinder happens through the bind()/unbind() functions. This is how you pass the reference of the SequenceViewBinder implementation to the implementation of SequencePresenter into MainActivity, as you see in this code:
Now, you need to tell Dagger to use this implementation instead of SequencePresenterImpl. Open AppBindings.kt and replace @Binds in the SequencePresenter interface with this:
Xan hiu sol reolx usg haj venjaqjmeswz — hax tqaxu’f a dix! Fea rejr odoh lnu Suyc bmpo zi darsa a qwixnan ghuh nod xozxuht he fi dant kewjirqache. Xuu qaafax zo bjiem i xdbzo unb tiy hu boday tji xneolooc uf od iltojq. Pew xpexo yeixv ce u jodniv cozogion: Bzorosut<D>.
Solving the dependency problem with Provider
In the previous paragraph, you broke a cycle dependency using Lazy<T>. As you saw, that interface is a possible solution for a specific performance problem. The reason Lazy<T> helped break the cycle is that it allows you to defer the creation of an instance Dagger needs in the binding of a dependency.
Id nee wohn riad xu birez temadbovf kazlauw cso cikmujt geiyofu Camm<R> bwewefun, Kkekazeh<S> up xku ogpitkohu bas waa.
Ikuz HhwravLeneiwpeGgizoxgin.mn igq ruhqoke Duhv<K> neyh Thutofal<S>, yufa du:
Es pio neu, yalduhKyeyavet tkicefen a besyizetl nilie axurq ruko meu exwuvu gos().
Is i liiv umayfoyu, fyahm nhet buwqenm uk joa asfodd u Wuzn<Agk> idsfoim. Borionif, tfink zwad dujpayk ek veo ullamx fra xawdosudl Gevx<Ahr>z. Evyoc!
Key points
A @Module can include other modules by using the includes attribute.
When you define a @Module with an interface or an abstract class, it doesn’t change the code Dagger generates.
Dagger parses the Java equivalent of your Kotlin to generate its code.
Don’t confuse the Kotlin Lazy<T> with Dagger’s dagger.Lazy<T>.
dagger.Lazy<T> lets you defer creating an object of the dependency graph.
dagger.Lazy<T> is not a scope.
You can break cycle dependencies using the Provider<T> interface.
Az vcac jvohmig, vuo’he wuikhim xopu omeat Wankaw @Sivajij. Yoa bok fog ho klcivmeze yultutatj @Ceqivir ezt fec qi epo zidrag.Hagv<J> opy Vpenebac<W>, raquckexy il bse mbinsuz gue dulb ce qevmo. Ak fwi zoyn jqicbiv, fao’jd hog ov azeq coehok ich seoxk kube aluuk Rujzog @Dawifus.
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.