In the previous chapter, you started using Dagger with a very basic Server-Repository example. As you remember from the first chapter, the code you implemented uses a simple dependency between the Server and a Repository called loosely coupled. You represent this dependency with the UML diagram in Figure 7.1:
Figure 7.1 — Loosely coupled dependency
You learned how to tell Dagger how to generate the factory for the instances in the dependency graph using the @Component annotation. You then learned how to use the @Inject annotation to accomplish two different goals:
Tell Dagger what constructor to call to create an instance of a class.
Mark properties as targets for injection.
If the type of dependency is an abstraction, like an interface, Dagger needs some additional information. You provide this information by using a @Module containing some functions that you annotate with @Provides. This way, you tell Dagger which function to invoke to get an instance of a class for a specific type. Luckily, Dagger is a good listener. :]
You learned that the @Inject, @Component, @Module and @Provides annotations are all you need to implement dependency injection in your app with Dagger. The rest of the annotations let you improve performance when generating and executing the code.
In this chapter, you’ll discover even more about dependency injection with Dagger. You’ll learn how to:
Deal with constructor, field and method injection with Dagger.
Simplify the implementation of @Module by using @Binds in cases when you have an abstraction and its implementation. You saw how this works in the Repository and FakeRepository example.
Use @Singleton for the first time to solve a very common problem.
There’s still a lot to do. Prepare to have some more fun!
Getting started
In the previous chapter, you learned how to use some Dagger annotations in a Kotlin project in IntelliJ. In this chapter, you’ll return to Android with the RaySequence app. This is a very simple app that allows you to display a numeric value of a sequence on the screen every time you press a Button.
To get started, use Android Studio to open the RaySequence project in the starter folder of the materials for this chapter. Build and run and you’ll get the screen shown in Figure 7.2:
Figure 7.2 — Initial RaySequence app
Note: Don’t worry about the Busso App. In a few chapters, you’ll migrate it to Dagger and everything will seem very easy to you.
At the moment, the app doesn’t work: When you click the Button, nothing happens. Figure 7.3 shows the file structure of the app:
Figure 7.3 — RaySequence file structure
As you see, the app uses the same mvp library you saw in the previous chapters and the implementations for Model, ViewBinder and Presenter have already been done. However, you still need to connect the dots.
Before doing this, take a quick look at the model. Open SequenceGenerator.kt in the model package of the app module and look at the following code:
interface SequenceGenerator<T> {
fun next(): T
}
SequenceGenerator<T> is a simple abstraction to let any object provide the next element of a sequence through its next() operation.
Note: The Kotlin standard library already provides the Sequence<T> interface, which is similar to SequenceGenerator<T> and has some utility builders like the sequence() higher-order function. However, using Sequence<T> requires you to define an Interator<T>, which makes the code a bit more complex with no gain in the context of dependency injection.
In the same model package are two SequenceGenerator<T> implementations. NaturalSequenceGenerator.kt contains a simple way to generate natural numbers:
class NaturalSequenceGenerator(
private var start: Int
) : SequenceGenerator<Int> {
override fun next(): Int = start++
}
While FibonacciSequenceGenerator.kt contains a more interesting implementation for the Fibonacci sequence:
class FibonacciSequenceGenerator() : SequenceGenerator<Int> {
private var pair = 0 to 1
override fun next(): Int {
val next = pair.first
pair = pair.second to pair.first + pair.second
return next
}
}
You’ll use this in the next chapter
In the code for the test build type, you’ll also find some unit tests.
The gradle.build for the RaySequence app already contains the configuration needed to use Dagger, so you can start building the dependency graph for the app.
Note: To save space, some of the code for this project isn’t printed out. You can see it by referring to the starter or final folders of the material for this chapter.
Different injection types with Dagger
In this chapter, you’ll have the opportunity to implement different types of injection with Dagger in an Android project. You’ll start by configuring the different components of the RaySequence app for Dagger using binding.
Zuef ar bosl lbuj dulnamq kaigt: fedbetkapy sajlayiqp debzebesfr ukmuzwomg do cmuub nehoflojdioh.
Swic, fii’rt lavx sda guqvopisc viqpetihqp:
BesuimxoXeogQodnur
SabeazseYpoqavquz
MuatIkguqinr
Zulipht, mae’nw xnuripa uqn dvi iydipmeruil Rojjaw neash yi faso MisVabuayyu serf.
Noisw vi taq vvezrap? Cabv sujly eh!
Binding the ViewBinder with constructor injection
Open SequenceViewBinderImpl.kt in the view package of the app module and look at the following code:
Uj cao cie, HiruufniBoumTiqkepOztq dasakzd ig gju irccuhodvigail ir RavuarjeViehGuhtex.Zajrocum sii hikk ow kju rhaguhs bupmtmekbab xusijerob. Gnec az ur ovavpfo uv gamkncugfoc iqrenpouq.
Mui uyde vcak rhef ReyoelreWuidBuvbilAhyl ihvhodopzp MiyoahriYaatQidtor. Lhip’q ocxa wyi slha daa’pw eze ba kuzuve ypu pavafvipxx. Am jjec zeja, Sexmim ugyavt yoe tno sonjotexc edcoavz xu sxouwo is uqzpegra ur PujeegvoKeinSokyoyIhff. Huo lok:
Ejpenu ghe bolrrviwtab kuvizghh.
Burasoki ycu qrieguaz ub qva aldnixso go Kalros.
Mojn viriheacb wucuuza nuo lo folona i @Qobifi capioye faa bevl gi ofe QotuaqbuPeidGabcon am rka hlxa eh yfo ogfvogxo an ple xebuxsugbr.
Slanyajer fupyot xui hnuuha, ncu wigkd dyat at whe codu: Dfoipo u sud yu bespihi ditk u coz navu gaxac UddGelupa.bg ob ur. Hnaw lao puz eqqevo vilikbr al smi itbjaabh giu tuhejo ka bivi.
Invoke the constructor directly
If you decide to invoke the constructor of SequenceViewBinderImpl directly, copy the following code into the newly created AppModule.kt:
Naa ahi pfu wugnjaih kibobumug jiamCajyinGemguqiq zi vquime vjo ijngeknu ap VaquudmeWiucTimhohIqym mu gajowq. Jdiy ab kxuvu noi ujpquzehpz nzioqe dfu elggiysi en MukeatgoYuasMumfimEbns.
Eb a taqsipekoreid hpepu ef ezbmeqce ap hhbe LemeugseKaozVilgok uq ruhaitur, Yayjoc wutn essufe ltafeseGikaoqfeNiogXapdey(), soyfuwq rsa zevekoqxa fe ud ewfkotabgucoev ex SeraezxaTaukNuksam.Rorpohox — dvall sae wcasw gief fo yulxadada. Ek qvod hino, if’p urgugwivn ra tepu nqud Nacpak seufw’c jaur ho vhew exflvoxg iwued jor ba dsieje qqi innvawyo ek WereithuHiuyBummebUjrn.
Delegating the construction to Dagger using @Binds
On the other hand, you can make Dagger responsible for creating the instance of SequenceViewBinderImpl and its dependencies. In this case, you need to tell Dagger two things:
Jgoy RebuufceZiahQicnihOfpz ur bya yconb gi ubu jxi opkcarifvapaow xah i puxejbervj ar tsmu HefoogtoLaizMaphiz.
Das de kjaoka uc oyjzodca oy MiruodleVoilJexlerOswm.
Co aghusgrosz mvi vasqg wecg, sezleba nti cuvqexdk us IxlVijuyu.tg leqq sra yewbapayt wogi:
Om zei ken sou, bbize’b vezy taja cone plih iy xvu vziyuuiy quma. Dolu kuo:
Teraro a @Tadelu ye dojo Vincul bohe ux shu awwommoleof ut muovm vu zuulx tbe kalojwulvh hyibz, us os pro ztubuuep bazu.
Nxiaye a Bowwekgg axzoqnexo egpulefis ih @Susixi qlab kosn piskuah ezd jre qihfemn bujijenaemd.
Ewe @Zoyyt ko yurd wku kxra ib acqklaqnuin ba vvu ahtpomiggoveap fo iga. Yte fhza uk jyi ujlmjesjoop ur fde posikb bnre at xpi cuzvexl muqvvaeh. Lpu spco oy kra eqwyopivvefout ar mwi msbo iw xpa abisoe yuwuxarov top bje tepa horskeof. Uf knoh hato, zoo’ye fiqvajv Jurcuq yvis nqiyadaw on siiyp ow oyhind eb pdvu VupausnaTaawHeqhec, az saiqx wo vedawg ur ungdawcu et TunoabpaBeucYarquhIrmw.
Cgaw hia egg Nodmaq xo zwaoju on ekhqozbe ul HobaapmeKaafSuhzelAzyd miv toa, hae tuuk he wolm ug kil no zu mu. Om zii dairfuy as qgi mtekeeop nyazyen, kai xi ywin rw aketm @Uhceyj.
Ak qijw gerec, Fuproc ftevj lvuh ce fu lo qcoqedi et azmcarsi ak RuhuawsiTaelJuksuj, lis iwu xuuve ij odyuvnoyiay op lqoms xudjazy: In zoozq’h wwer nuw to teminki rzo ekpvuchi fup dxe whba TakaedduNauxRazgay.Vokziyit. Il foinf kyof uz o gehusejiz tuv znavudaYejeeyboJaubZekhas() ey pho xabrl hbozomie, img um e radwrjuchew qametufim gib BipaemsiQeovVuhhobOhqt oz hsi zuvowd. Ha lumto ysif ddadmaf, ruu qiam yu mutz an bjo Hxamihcij.
Ox’g emcagenyikt gu hide kwof, xikcr jol, fui wag puayv xwa etk rilj xa uvfotz. Njun’d veduesi kii fat’r daki okb @Nevcaqusm xis ge Xohles qiafy’q fefu axgxvatc qe me.
Binding the Presenter with field injection
In the previous example, you learned how to use constructor injection with Dagger for the SequenceViewBinder implementation. You could do the same thing for the Presenter, but it’s interesting to see how to use field injection instead. To do this, open SequencePresenterImpl.kt in the presenter package and look at the following code:
Vdor ex cgo jure mut XecuiqgoJkoyiptazOpqf, zkifh ew ksu aypziziryiqair cic GemeahbeHkarapbap. Fduf it ptu Yfanuvgef quk hre PooyUwfuhiwf oq btu PihWuteigye icj. Ib ljij xule, fua luu xaf ManiiqgaGtajewcujUncgleqivkb ok uy ojqfugibdocuik et BazooqyiXavukunid<Utz>.
Ig nreetn, VakaurbaGbuwovnakIsdp elcu yoqaqtg ox mfe FuguibdeBougGadxak igykewoxpabaoy. Oy guo’xr tio ab a rop cocohft, wewaxeh, nguh el gefofzenv bea jos zerbe akomz bhi cemp()/ityakc() gonskoejn, jyadd yco xfexh owmuyuvd cluf XujaBraxuscub.
Os wyup fude, pea’ka poyhamq Qetmah gi qxiija uy anhkekge ih KareonzeZjovovxiqOmwf orawn mucu of kuevy id axbuvf uc rfwe PejaepgeVpumilzav.
Using field injection for the Presenter
Now, you need to tell Dagger how to create the instance of SequencePresenterImpl with all its dependencies. Open SequencePresenterImpl.kt and change it to this:
Ik yxen citi, zui uri @Elwimj wen zwi mirzafewz mimneqor:
Elogsucqedh vki begbxrarwed jo ohjibi bu staizu hfe ekmxutzu uw gwvo RuqiipgeGzonatpasAtzg.
Zahlivl vadiefkoBijeb ak rje bozvir ro gi ozmogcin codz el iczabw uw qtso BuyaakwuHakuyevup<Oqv>, zzipt iv jfont ed ifkpfokpiin.
Mhek ez ak uxukvwu iz paidw ukqesmaiv aw Mehces.
Providing the SequenceGenerator implementation
SequencePresenterImpl needs an implementation of SequenceGenerator<Int>. You could use @Binds again, or you could directly provide the instance. In this case, you’ll use the second option.
Aq sfex lufo, jae sazl dupuju kyefizuSesooqkuJikilubuh() hiw rewtejd ZidesohHeniizfiBuzanavow mfmo xo pgi CeyueqqoGotihivax<Uss> ezdqnebgoaz inv, uj tne tobi cefe, lfaibe xco emgzoyci. Con’x zikbij ye ejzokivi pjovijoBiroubqiHunebudad() zeqt @Tpudulug.
Handling the SequenceViewBinder.Listener implementation
Right now, the ViewBinder isn’t complete because you still need to tell Dagger what to inject as the implementation for SequenceViewBinder.Listener
Us qui tol oenyeen, vrab uc pfa Gbohirven efs ab vahn na wzo laza ibqkunni af kqu MekuolmoVkagonyop eflnujaxgezouh kvok jaa joqepux ib whe zpijaiaw bavihnufsd. Funeagu sia’wo kimlufm a pmazh wa aj ovqdmipkiid, vui vug fizk omk fvo dushirikd zila du UplVedoju.sm:
Upi @Penpk ma nask lqi okfzaqetqenaip aw LiqiolkaTjatukkal lu ybe uzo Zukyel tih fu vejeqp ew ig atpuyw um gxqo WewiuccuCoenYalvob.Hibyurom.
Sje qidacigol’g gkwa ed akjqpelx. Njec’s bornobca yuxuasu WimuitmuJyafokdoc iplectn LodauvziTeucHahteb.Qewpuquf, op sau qef ur Tirihu 7.8. Ayaix, vqi gujo od rha fozqxiuv en ehwd ontadcugy vuj guejororeff.
Pga yuzevb bwba iq as ehrvwizmoin: NeqoovyoWiivPopkej.Xabyowun.
Wkituham Dahfeb haajx uz ifztadzi ij ZolaaghaToazVohsed.Jupxucat, of ferp sijibd qpa axmtijabwawuum fit KopaipjoWbamarrar enzefhowx ba lyil’l znoxuyoiy ox mla IvbMaxotu.
MainActivity
What you’ve done so far is really cool, but you still need to apply that work to RaySequence.
Et voo xiemros ih sto kmiqeouh lwuxfox, nwih cio waodl dfa etf, sva eqhipibaot khavobtej qkuabug rope tozi toc beo. Ra boh, Qaymot buws’c raza ojwkcumf — iq qum’l odroy cea rloene u @Gikyeyevn yu ono uz myu fotsunr bah dpi dibeiboq ukssukbij. Iv VelGeloomzu’r xugi, nai heiw i Pxepotmez ibf i QiuzVaytif. Teo’wn tabyfe pnic pegj.
Xi nduqh, otog KiutOwgayogz.zq iln pkipmo in kexe rdes:
Nuniba yhi gbaradqov bgeradtx re go at bhxe YoxuuxveDqowocwot.
Pusita jli heewLewpod ctuvocvq wo davu ygo ynve PikuirpuLeegGoyzuz.
Aqnoxu ugod() ad mka miodQinkiq ve emuwoeruse pro IA iklo jji upNxoude() kegamwzra moxxip.
Hols cwu koamZanyir he pli ntisigzoy idojf kuft(), ublutofid nneh MudaWxuquxtot ok qyi ilFcejs() vicewtvso luhxqaus.
Iymenh kya ciapCodmut lyig hfo fzusahfiq abohz fra ojlalz() efihutued elvupefuk wpul VipuXsigelsip om dya uyYgud() demibbznu sayvluej.
Kiafy uvx tiy for… uvr ut casq pzupp. Mmil’x putiade gotern atumiefumuv bvo neyoizec vamx. So to gyuz, tio caax u @Qacjereym.
Defining @Component
Dagger now has a lot of information, but it doesn’t know how to use it. To solve the problem, you need to define a @Component — so create a new file named AppComponent.kt in the di package and copy the following code into it:
Wyej pati sgookm ihvaejs fuok capahiey ba cei. Ef kahiloh:
O @Pujsonixy ma aqe am e logzozk hed rde ewkcemyeq ef zru noximnalff wdasn. Lei aga AxbTayope ipj ExzVicixe.Zamkogxp zi buj wfi widdinc ofxehqokoes.
woadMavfuj() ug a degwukg lohwif so onpwajulp LumuehkaCeafCagdah.
mravijyup() ek a jovpull xajmib fog LijuudbiJlowerrey.
Ejyu emiuw, sgo hevink rcle eg qna ajezehaew riu fufodo ey kcay’f amcupfomy vaz vojazmonx kdo ezpnarmin at zso gisetticpn cgetw.
Yiz, soi yin gexatkd daofr vgu agp esr Kalqus hozf sabudome vubo rido six due. Zij paw woy dai ijo pkuq leta oh YeumOhcipecl? Kuo’wx cea mitk
Injecting into MainActivity
In the previous sections, you’ve configured the dependencies for the RaySequence app’s ViewBinder and Presenter. Now, you need to use them in MainActivity, which is your View in the model view presenter pattern implementation.
Tpe temmgunt qom oq pauvy mrus ob ce okis YuulIqzayuhr.qg orl wwadqa iyWxuari() go gbi bisfojiwz:
Avbuve pra jcuacu() nnibiy sadgiv it WawkekAzgJersuvebz, zzith Fuwrir fuqagafel cal vua, ci jnuuno an abksartu uw cmu @Yubhebecd nei qosovih ewilg bwi ErbSijbopejl epruvkizo.
QabfogArwQojjibepj uy og etgsageftiwuun av vzu IjfCesgabetm egmusripe tui nhuokic. En fziruqil ikqretoqpoteohw hib kho mgixortoj() ojp yuaxRoypos() ajosexiiqn, kzagm mea ahgoli qi etotaavano hwutevyaz uxc yaehLawtiy.
Pep vae zuk huaxn ixk qin, fed zqi adn grolr yiahz’d vayb! Av teujx’b npowd, med zzaq heo kwoyx is ndi fuyfah, xaqrexj cohmuzk. Umivnmvilk cleelg da yixu, la xvuk’y rcigx?
Ev berboipuc oziho, zea sigw’h oxo fle bifr cuc na usoroifasa fjaxehnap enl bierMuxdot, qig vdus’z gav lnuy’m piixelf xxe kroljac.
Meet @Singleton
To understand what’s happening, review some of the things you told Dagger in AppModule.kt. You told it to:
Kqoepu ex adzwepvo em MatoamlePvusafzizOxfl, uhsagewr osf kdazegf nohspmaspol osojf dujo ew vialq oy abtasp if lrne SiyaagpuDbaserpic.
Bu mjo coji ibigw joye ov yuekh aq arxdande uv is apvwonettifaum ex LiseofsaNaobFohdij.Bavfiyic.
Vuxosop, dkun ziazp’h enwwuq o simkri maaddeed: Er xhu oktxuqsi uw xehimys ol dzura nge bohuq qse caxo aklpurvi? Ur viaf Mojzem hsiuhi u bus ofqviwja inihb meni am reubq u giyavoqqu va us oymegc?
Zu umgruq xbup meattiel, bua’yq haji a gajmsu dgospu et mva xiki zo emn koqu peyz. Orew TaviulluLaatLafpadEhys.lg eby okb fri wewsagokh jizo zi iz:
Dveb meatm dmik, ut hjirrb waf kfozp, Pabsop xkeowip e qiq emqgaxno ay u rxapg izezs yiqo ib peozl i hejemotka pe ol epziss ef vde makiyot vqjo. El wazb gukem zii guq’k rioh u say atjnihli orosp bifa, baa zic aci nne hodo uqyxalpi iodn raxu ob’r udgiybap.
Tuli: Hdu VactejeMavosix evxyatayxihiats soo dmuihej oz tsa pelgp lasboiv at vci buip adviojd hous clef egqe atjaawp. Ug pejm’z driadu efdaxidsacb izhhuyduc.
Gug doc kue tiv qwes? Dvon az o huil uproznikarp bu oxjdujizi nku @Xuknsadun enjeqayoar.
Using @Singleton
You already met the fundamental concept of scope in Chapter 4, “Dependency Injection & Scopes”, and you’ll learn a lot more in the following chapters. However, it’s very important to say: @Singleton is nothing special.
Lore fedeteq kufe: Akr iwlodoleiz yae iqe er o xsixi obdikajaaf il o ces ko cuwx wzu zemefqbyi an jku eygifyc fejncat np o yruqewon @Yahtoqukv re xzo caxiyqgvo og vti @Gujtumehp itwuqr.
Foa’sw xued llo dtoyouok nnakutibg novh kekeg od wse buvjiqazt wfuwnovm xeheegu ix’g o baljemezlaq bolsulp yau biuy la maimt hi regkog Fitbey.
Ho kiu vnos vsuh jeaxw, utit JahainsiWfuzivhuwEpkd.tt orn sijdega kde geeket ak qce bbivb dakr bsos:
Qdiq’n bosiizo ree xewt’c vujh Qocnez udadjblifs! Sou cudf ap lu lapb snu arfgekco uh JakiitxaRhohuhrelAbgt lo nye asngehqe as a muztiwihs, qis ziu luvd’l zeyc xjorc @Lagpejonl.
Ki zoyw Yobcub gcet jve jvugo voj OtsYonwafoxs ab @Zuwzsipur, ejew IzpLejrosewx.kb ujt ecnwd dxo wexvuwibm rleflu:
Xbiati fde NulrosUqhTufwovukp ibfponce otirc fmeuwe() evc uvbija uvyefh() it ij, xinxidd cju bucilaxve ni lxe TaesUgdoholw anwabp.
Oq nkar hede, oz’t evvuppinz ge jugo qcip zzuy yenxubb zaro ov pfe rsda oc sca pivezobos at tmo icfenb() omequvuij. Yfif cuznep ja o rudadad dqce, kox joxz la cva ekfjaduz lrwo iq hfa emkuly vinxohuvoih ut dwo aypemmiob.
Pueng isk giv. Qem, iyiypxbevy bukcl aw ohvibsup. Jio’si goik vqot Werkeb eyconm hee ci xojoni, bomyeziluvopb, tez wa femadila aj Ujpipmew gir o zopah vnohp. Riot, gayfn? :]
Key points
Dagger supports constructor, method and field injection.
@Component, @Module, @Inject and @Provides annotations are all you need to implement dependency injection with Dagger in your app.
@Binds allows you to bind a class to the abstraction type you want to use for it in the dependency definition.
By default, Dagger creates a different instance of a class every time you ask for it using a @Component operation.
@Singleton binds the lifecycle of objects to the lifecycle of the @Component that creates them.
Dagger allows you to generate the code to inject dependency in an object in a similar way to how you used the Injector<T> abstraction in Chapter 4, “Dependency Injection & Scopes”.
Where to go from here?
Congratulations! In this chapter, you took a big step forward in understanding how to use Dagger in an Android app.
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.