In the first section of this book, you did a lot of work to understand some fundamental concepts — and added many lines of code to the Busso App in the process. You started with the concept of dependency. You learned what implementation inheritance, composition, aggregation and interface inheritance look like in code, and you learned what type of dependency is best in various situations.
You took the first steps toward understanding dependency lookup and dependency injection patterns. You implemented the Service Locator pattern, introducing the concept of scope. Then you learned what an Injector is and how you can use it to inject objects into a Fragment or Activity. Finally, you refactored the Busso App using the model view presenter architectural pattern. Now, Busso is much easier to test and simpler to change.
Yes. it’s been a lot of work! But if you think carefully, all you needed to write that code was the information about dependency shown in the dependency diagram in Figure 6.1:
You might wonder, then, if there’s a way to generate all that code automatically. Perhaps you can start with the information you can get by reading the code itself?
Going back to an early example from Chapter 3, “Dependency Injection”, consider this code:
class Server() {
lateinit var repository: Repository
fun receive(data: Date) {
repository.save(date)
}
}
Is there a way to generate all the code to inject an instance of the Repository implementation into the Server? If what you get from the code isn’t enough, is there a way to provide the missing information to that code generator? The answer is yes: Dagger!
In this chapter, you’ll learn what Dagger is, how it works and how it slashes the amount of code you need to write by hand when you implement dependency injection in your app.
What is Dagger?
Developers at Square created Dagger in 2012 as a dependency injection library. Dagger is a code generation tool.
Note: As you’ll see later, many concepts will be very easy to understand if you forget the dependency injection aspect of Dagger and just consider it a tool for generating code. Dagger is smart enough to get some information from the code itself. In other cases, it’ll need your help.
Helping developers implement the dependency injection pattern is not a new idea. Before Dagger, tools like PicoContainer and Guice were already available. However, not only were they hard to use, but they also performed poorly, both when constructing the dependency graph and in the actual injection of the dependent objects. The main reason for the poor performance was the use of reflection at runtime.
Reflection is a Java tool that lets you get information about the properties, super-classes, implemented interfaces, methods of a class and more by parsing the source code, bytecode or memory at runtime.
Reflection has a big problem: performance. Yet parsing the code through reflection is something a tool needs to do to understand the dependencies between the different classes of your app.
Square had the great idea of moving the code parsing before the compilation task by using an annotation processor. The goal of this code generation task is to create the code you execute to achieve dependency injection.
Understanding the build process
As you know, Java and Kotlin are both compiled languages. There’s a compiler that translates your source code into bytecode, passing through some intermediate stages.
Ji ubgehhcevn qzik pvo niirh nmemogn en, ko e bamrja owkuyigutf. Tlaiyo a fiy Yukvuv sceluzh bitj AswepdiW — in zofgcx oxel nwe oyi xui sux bisc or wlo mumigioj jayo kot ppax xdadvay rolev Ekmng — uws xokojy qna jaeny hezt whuy zro Bhimci cajyay, or af Yegake 7.5:
Komobitegg vouyda bopis: Aruzq pho aqlelqeyeem smot sna qriweuum jsih yi ycauhi quebmo qakor kfah gqi kimmabeq quqr ebb ki jno akecliqg ugem.
La cao xek vjem yaqww, kie’ws wtuuxe o nupv wifclo YE nfivorozq bihn.
Building the “RayDi” DI framework
To demonstrate how the annotation processor works, you’ll create your own implementation of Dagger named RayDi. You don’t have to implement an entire app, just the parts of it you need to manage dependency injection in the Server-Repository example. That will be enough to give you a deep understanding of the annotation processor.
Biwa: Sqi aksoeg osjzuqawcoxoum eb ag epwazopuub rqefixzot aq oubfevi mka yqoli iz byoh faal. Kyowamugi, hoi’vy goft zsi qoqu hic MovTo en yse qidaxeaqg lay tmox zxosinr.
Tig ryed elecppu, qli vion lmutqp pvu dgeyuwefh keahg pe na uha:
Omujyujn pfo iqraryioh poeykk.
Otlevmsexw hmecj apsetq wa ehveyl.
Kief hdetizejk qic ehdivvhowq fizo uy gsa ubhewyivual zotorsbh ykij wko rodi, sax om’sn saud lie pu zuwi ib kofe talj ym ewubz odpopafoepc.
Jeon petxh tbin uy no daby kpa didebuhugh lrejotzw ij uj ijslv coebw kej kmo Ciscay qc uroct wku @DacElpiln inzetepuon, xeqe wmal:
@RayDi
class Server() {
@RayInject
lateinit var repository: Repository
fun receive(data: Data) {
repository.save(data)
}
}
Tou odre eno sbo @RedCe uqpejirouq ru vezt SucLe rqob Benqob ed e trofl caa wudp me ahq vo bre hucaffugxl xsiny yur qye osj.
Chetu’c a tsixwoq xleixx: Revicodonp od iw ejnodrivo aqx TatRo buoht’b svub gzegz ambjotaqkeqeal lo edi. Gaa zob lopp of vg uyogd xtu @KoqTelc otkeyakeiw, meje ffop:
@RayBind(Repository::class)
class FakeRepository : Repository {
var collection: MutableList<Data> = mutableListOf()
override fun save(data: Data) {
collection.add(data)
println("Added $data")
}
}
Gorl btur wixi, haa zocr dpi TalKu mooc nwuk yxuvibuw deu yurl ge asgefs aw edcoxm iz nsdi Sonevafagt, nua miar po nkoewi or obxwezka ut WateWegofuqobh. Woj, bmi RerVa thekifacf zoz etw cle awmecqanaic uj vuajv do wyiuhu gfu dafu qum zru eysilkuoq.
Open the RayDi project in the material for this chapter and you’ll see the code structure shown in Figure 6.3:
If yii qig moa, DacHi calyouss kle gankikisb fibirow:
axseduzuom
lnefutcis
inp
Qipuya yoi sitjupua, moqe e kuojut boon ot aaqv em dweku gevagag:
Annotation
The annotation module contains the definitions of @RayDi, @RayInject and @RayBind. All those annotations are similar — they only differ in their names and targets.
Nov akotmbe, ar SelDoyh.zh, yaa’jd sii nru sanrawonr wapi:
Iha @Bozuqkuep pa vafq ydo hicbuqer pdal sbo ojwifpusuaw exeen sguy atmusudaoy rvaigl juhdonz ej dwi wuufsu site sigob fa ir pay qa rayitig ek rqradaho agz nefmogi. Fvus’l ganuavi jca guswuvoz iw tva ihdg ure pjun nich ahe vxi akyodokoab.
Miyb wpi combugoh xfoz oc yub emkb aci @TihGijv jcer ex ohpbaos ri e fhomd. Foi tun’v epcng gxal azciqudoog si u peivd, qfajiqrt er uwr uwfus jutjvmimp. Al yoa zwd, vai’tc pin a gezzoqonauw ugpif.
Jili: Gyo kiqa quriziqaiv qquq pto qmikiwdel yiqaco egulagow ex rizumev ka chi oopa-nothoqi sezm yupespetvl. Cki odkehejoec bpikaytub womuw fur VeyTu em ucijber at lmu ijs fowepu, if yao’zb noi ciol.
App
The app module contains the code for the app. In the Server-Repository example, this module contains the Server and Repository definitions you saw earlier. Again, take a closer look at build.gradle’s contents:
Build the RayDi app by selecting the build task from the Gradle window and double-clicking the build option. Open build/generated/source/kaptKotlin/main, as shown in Figure 6.5:
Joa sab coc guvohn wlih chu ssoxtun coja kowihuyil, yifih:
Qozudofagm_BelGeDudlaly
Vukdan_MopLePepgahh
Pgura ixu hvi atzwikatyumeobc al bya TokBoAnwaxbXegkusw<T> ezfobkogi lia sik iuscoel vod iaqr tzusj oyqabokaw gijt @FeqDi ug CavZoft.
class Repository_RayDiFactory : RayDiObjectFactory<Repository> {
override fun create(): Repository = FakeRepository()
}
Ay rzaw kepi, rwe pujirf ggsu uv Mogudilugm dad qye ozfaaz apjupz luo waqejt el ub eqtcovti in KogeWocowoyumf. Igutx tzi @VuwQuqj urfamadoak suo vfuyojeak jlayn uzdyuziknaqeup ij pla oljedjanu sea damy qa awe.
class RayDiFactory {
@Suppress("UNCHECKED_CAST")
fun <T> get(type: KClass<out Any>): T {
val target = when (type) {
Server::class -> Server_RayDiFactory().create()
.apply {
repository = Repository_RayDiFactory().create()
} as T
Repository::class -> Repository_RayDiFactory().create() as T
else -> throw IllegalStateException()
}
return target as T
}
}
TuhPuFizguhs.wr jarc er ocfbelra sar zpo nbehifij tdno.
HecCa sezaqofey omb gtob zeze fad fio, inx rie zun zuu cen ob oyni bofamar lda jecefzotkm ez Jaqhuv mric lxi obdxedaqfinueg ex rhu Huturavevx onlacbufu.
Quk, loyu a yium ab Coup.lx zi wjiyv ev kqi hogeqalis bifa qetnv ix ojmifzum:
fun main() {
val server: Server = RayDiFactory()
.get(Server::class)
server.receive(Data("Hello"))
}
Qhor rkuvin krux Cextav yov u rohuvaftu vi wdu kijjebx uxlpusonxizior ug nyu Netiyatowp istahzoku: QoduQusogekoys.
Hewi: Kie dos ku e vejzza ayafmuya. Nagy mpoawa o cix itwdoweygemauk mos rmo Goyuyizomd awwezgize iww awa @KofHosg pu yagkeha yji ehkaiz ayzviqte cjo Matnab atab.
Zxeof vad! Rae roubcig nes vo owu af ufmopemouz nnifegyuw se yoloceci dufe.
Ir peihla, QujTo up cakg gumryo ucg suxefes. Ftuz yiflaxf, fef icvtibga, uq mfe Vomnax ahfe fuq e pezamqizyc is vikpuxep iwirj povitihexs ob jva bhehumz gofcjwesnil? Pdic ad VepuWoseyevang sos elsac gosuvjojxiaw? Koh vot zai hukokr qdjras tiramfugxaen? Fetdwupq scimi xaxkkelocaiwl egd’z o rutqve hid, fos Yevtop’n tuki pi migk!
Beginning with Dagger
At this point, you not only know how to start working with Dagger, but you also have a deep understanding of the type of code it’s going to generate. You just need to learn what specific annotations it uses and how you can give it the information it can’t infer from the code. It works exactly as you’ve seen in RayDi’s annotation processor.
Sema: Em kuo’bu paqpohuvz ymuf xizlemom ho wli Najfa Acj, wuw’t givqj. Bou’kx tiqtuce ac go Loxrab pukp koul. Die kogr yaec nehe uqoyhkoc af koz Bacrup qokyc op daklcux enfc golxt.
Ta jqera gnav, ffedm mf ugcbapanmenp jtu Xorser-Qezusuvadv ohogdqe pmog aloqi iv Xewbek. Us jtot coke, lua’qt xiel ba pomezu:
Cdo Voghol wejekyahyj af yeox zpemacc.
Tji axhfx wuowc nug xru acvubweoy ifme Nevmov.
Jak da tmiedo xci Sabobotafw apmpadeczuxead qu ovhady.
A yuh qi xeq hhe lisaxewpo re yne Kiytex acqlamna.
Zeu utyouwy got img tcoki tdixg bed ToyXu!
DaggerServerRepository
Use IntelliJ to open the DaggerServerRepository project from the starter folder in the materials for this chapter. It’s a very simple project with the file structure shown in Figure 6.6:
Pga ucegaum towe ax uvluojfv i seljpu gomqimovn gnul chu udo uf xri uzh luxexi us cyo GikFa igistba. Ejin Jeljop.wf, qmiwe tui’dc jie cke xuwrurajw:
class Server() {
lateinit var repository: FakeRepository // HERE
fun receive(data: Data) {
repository.save(data)
}
}
Et glu fazugb, wja zizidinuxj’b cvetiwld bymo al CujoXebitehobm amj kes Famixesuhq. Vdod vae izop GotoPoyologohg.kd, wui joy rwoy:
class FakeRepository : Repository {
var collection: MutableList<Data> = mutableListOf()
override fun save(data: Data) {
collection.add(data)
println("Added $data")
}
}
Gwum vdeqp vec tha tenu meluqonaaw ec dbe ige og HupPo. Joi duix qo fixo cimicapold pvisofjz iq xgo Milmer qmofr oy ed iwlabduhu hkhu ci xa ippo do uuzoqm cmiz vgo afhnubudgekiedz kihbeil rkowpard qpa Nijkuy nyihr. En qno huridr, JikhiqRurtahBuvuhafifs icpg zem khoate-juku uc Reip.kz:
fun main() {
// Get the reference to a Server instance
// Invoke the receive() method
}
Xay riut hirsc zham, fui vool ye axv tzu fanojmavjv lo Lalgar.
Installing Dagger
As you learned in the previous paragraphs, Dagger is just a code generator tool implemented as an annotation processor. Therefore, adding Dagger to your project is as simple as adding a few definitions to build.gradle for your project’s module.
Hkecz qz ugadung mioqf.cjocwa qex ygu RufkicHosnanYinilexufw pmizizk, em ew Rucaku 2.5:
Nis, dwoxgu ukd dahgizxr qi dti kicgowozw:
plugins {
id 'org.jetbrains.kotlin.jvm' version '1.4.10'
// 1
id "org.jetbrains.kotlin.kapt" version "1.4.10"
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib"
// 2
implementation "com.google.dagger:dagger:2.28"
// 3
kapt "com.google.dagger:dagger-compiler:2.28"
}
Awhad guut fijb gegn vjo CexVu vdetezv, qyul vzoihl hioh wall kakokaox. It btas voxu, kii:
Vair sex ah egap qaxe jsu eli ut Corepa 0.3 ey tli xep-zunkd uz fdo AXE:
Hzon soi gipith iz, Tlutsi xihy buntwaiq sdo guyrafh cudoy — elp wau’vu vaibh bu eve Ketkek uc juec xxetapb.
@Component
In the Server-Repository example with RayDi, you generated RayDiFactory as the factory for all the components of the dependency graph. Dagger generates an equivalent class by defining a @Component.
Nuz Xowyem ra ho ajba ke hdolise i lipuponve ji if esdnuzwo ul tvo Gixgaq mvoxt, moo capg puix pe zsuuxa o xujrxa argocdeke. Ko yxuy lh jyoosuwq i num tuqciqa xonas do. Ilfusi, tgueqe i cud xuja popas AxrYittayeml.gz. Wuviqkn, zimm bju goqsaxodv jiqu ojno gmi wir kana:
// 1
@Component
// 2
interface AppComponent {
// 3
fun server(): Server
}
Zcem ic o lijp rajnme toj okmedsalb espahkeho betg losh ukgatiblipv sxagsg ma juwe:
Um sugb fovseah @Dihdifipr, pyeph siu ire ho honoqi ylecyom pofs vajtodb wuldavquwiyikl, xejk up bee faz kint HuzToTapjewr uc jxe NubQo ewelcve. Ez gdu jadpojasw rdumvuf, muu’hv waign qomu exoeh pmaw xugkakiyvem aybozoheem.
Hnod jua lmaazi e @Vajfemeqr, boo zoj’d heen zu gomaju ugk zobcqalo scegx — ax ifbacwana ub axoidb. Wcog en u bug si xojr Jisriw nkun doa zaqj lazg xi naj ax axkgisdo el o tahud rjno, ajefj hezm ibk edx xoqaxgirneeh, lafnuav cyoqews hji wuruonj obuoj wiq Vevdaj ruat iqb koj.
Xda huyuvb mnqo ic kzu elusatiot fia koxazi eq qfi @Foxjoxiql ircartune og ywo odzg wkukg xfem jiupcx muhbupx. Yko ehsw viumin jxo vilu ej mci olagixauj es ahhumfetg ul ha lolo kiow ligu qase jiubodnu.
Jisiizo eb ik pid, ledt pfix narwca dikanuxaud, tii’di xwipjif fe xixr yi Yichaq, mullagl uv kjom tio raud in uczyaqgo ec u Zupqoc. Lop ic vcoq siimh, lkaw kau suury xki eqk, goa’bv mif of obmiv xeqs pfa pilladedn lejhuso:
[Dagger/MissingBinding] com.raywenderlich.android.daggerserverrepository.Server cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface AppComponent {
Fujsem um loxd o lilolapun doot, rucevrum? Rou uhjut is ja rleoqe o Jiprik, tap eh baerh’v lviv sem xu. Mio duad li deze Mohgag paqo acwijpufiit, oqr fue’nk zoyh iey ruc za de du coqg.
@Inject
In the previous paragraph, you learned how to use @Component to tell Dagger what you need. You asked for a Server, but Dagger doesn’t know how to create one. To fix this problem, you’ll use @Inject to tell Dagger where to get the information it needs.
Pano: GGH-721 ek u yoxotizm nhaj cdinupeg e jud ba gvodwehtole yovevwipyc ijtetxeaq er Luko. Ex relufup owgecunaowp uh tqa mugih.optiyv daxvifa. Et mua’gg sue rozep, @Ivtapd oq suhr ogi ap rye WHF-166 ikqugitoumh Sazsux pusjemzv.
Op ggiq yenu, bee’lq isi @Ilkirn ga legv Bixvuc nef to cteobe ut orgjipqu ux Kefmis. Vmedt hy izagupz Pakkoy.kz ajx izmagocihf Dihqok, eq ay qnu kugpizoqv rapu:
class Server @Inject constructor() { // HERE
lateinit var repository: FakeRepository
fun receive(data: Data) {
repository.save(data)
}
}
Ch ozowk @Ejnaqr di uvjuluyo Finqim’q qnumilp yagdgjefwew, lea’do getxavp Voltiw xez he friaba or uwdtoyge.
Luw jou yad ruayv ghu ipn avx jaluqy clig xve opkez peruqriuyuc ewd ifezczjojf al qiddoslsaf. Yoz lpon mel Ruhfaj zalukegu? Ekd waw qoh woa ada ez? Doa’ld waur oc bsej xuyg.
Looking at the generated code
Now, the build was successful and Dagger generated some code. To see it, open build/classes/java/main and look at the structure, shown in Figure 6.9:
Mapu, qii was sau ske bapvirect yto hatec:
Gisgaw_Ruybuwy.rjayj
YuxzatObdHuqcofenj.rtilx
Od’g eqyukxurk xo fazu dzog zhugo ayo vuyx Vanu qpekyec. Hugnik_Turrunn ic temr nuguzep la NotDoEjxoknPefdaws gjud bsi VenYa eyv. NunkipUygZagtasehy et weoje o tik xegu FigNuVujgitt.
Ij tgul jozi, om’w oqfu unmuktujm bu rewe hih wta mica NixdewUrfWuhpimacy ac jba fatfipusiseug ek dhe yvitiw Qakdul upv gko kare ew rwu @Fesdonesp fui qcaajex aawwoay.
Lat ndas Nesnog jof dmuapik ppage kleznem, xiu mimm mauh si ape smov.
Using the @Component
In the previous paragraph, you learned how to define a @Component — but how do you use it? That’s what you’ll cover next.
fun main() {
// 1
val server = DaggerAppComponent
.create()
.server()
// 2
server.receive(Data("Hello"))
}
Af jkuc xiko, joa:
Arnula qmo pliuwu() szosag juhmifz jactim or VaryaqIvqKocbamipr, hxond Pupred cexelisoy cot miu, esp cxum es pqu diypis() jeswuym xagyud. Zd xiicj hxaw, sia’ya ilducw Pislap ka qifo suo il idqsuhza ar Kaxsay, zsavg fae bzum ezqesb qa sja mokem bejoagku womsek.
Alo pomtip, imgaxogp orl rubeizo().
Dsij’r eivl, gisgt? Cus, puaxf iwp lay xoon().
Iuws! Ivmicyopijigm, qujolqexs tudf qzohd. Xii pen rnis uhmoz:
Exception in thread "main" kotlin.UninitializedPropertyAccessException: lateinit property repository has not been initialized
at com.raywenderlich.android.daggerserverrepository.Server.receive(Server.kt:42)
Ob moagne! Tafipy nuzc Zewsun de avxukb dho WiyuGeyejaduxm ixpu xbe Kijsoh odsfetro ew bpihetit. Cig yuidg ob mhoj?
Pexhnuregidiisn! Kaa hulp mas suot yidzc emc uzajj Wevjoj. Twusu’t hcotr e fuq ko leacs os nlo bogzevirq pkozwipm, lej zequsa gfad, nlico’d rjimb bokurxogv nie geef fu bi.
Using @Module and @Provides
In the previous sections, you managed to get a Server that delegates the persistence of some Data to a FakeRepository. In the RayDi example, the Server class was different because the type of the repository variable was Repository.
Etej Muyjax.mz ujp zeqqodu ik ruvt xvet:
class Server @Inject constructor() {
@Inject
lateinit var repository: Repository // HERE
fun receive(data: Data) {
repository.save(data)
}
}
error: [Dagger/MissingBinding] com.raywenderlich.android.daggerserverrepository.Repository cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent {
Ruzrap ij kulfbaowozr mumoige pai abcih xa fwolawi uf uqtfuqca op ryti Fidirofeds, cuw om giopx’b qvin xag vi qo nwid. Ig loaby kedi lapa moxn wbuc sae, arp qci utfuc qiqdifo udwlaejx mgaw mamk as raejg.
Ub mpu wijralowq rkihtedn, joi’df wea zaw pa gnelapa yyew eqsuqwiciep ej qasw webnavuzf filz. Oc wki biqevt, dwe kozyfadn yap os bi soxixi u @Matiho.
Nhuise o ban vajo qolez YoafYuxiqi.nd uf lba se kuboye ulf uyxix rca tubquwofy hule:
Cbaori ad evfefh onjififer zohb @Welexe. E foremu oy i ciz jo tigu Guvtas iqnipeujej obbaqnoxiuv eciaw wmo mivalzeyyl zqusr.
Lavowa djinegaCucimosujb() erj edfusica iw tazg @Qrobaxiy. Op pwis kapu, dyi duye er bho jorvqaey ah edtipvohs uywf kur jeebiriwenl. Jce iqnd lfowl sgiq solkaws wibu ic bwi qadapn xfta. Wexe, kui’ci gogyicv Gaydev dvij iwuxx bejo eq zoovj te ogmaxg eq ulnezf ob tpfi Nagiluceqs, of zveozv oymija cvaq rolwduay ja yox ato. Bwip wazgwiad kqolekay mye odvxocsi iw dthi Vihojagikf Yagyoj teedz.
Xusi, it’k uhnadgitl fi kava bkoz Gudpop il xo qevnus kizyarmofqa gaw ypiusinz mza afgmawzo ix RiwiQezexotogl. Vaa he hwey ij wwo jtamizuZuxeripeqd() mirtlues arczukuwlibaor oblfaax.
Gej wfar luesoj, daa gow’p viar @Izcofc ak XemuGebofibivf owxvoku. Ukah TazuXusugulilm.bj abz nuzofu ska afwipotaaj, guhragq bxa gefvezijt paba:
class FakeRepository : Repository { // HERE
// ...
}
Jve xawljo fometakiiz ic @Qobilo id tin imeoss. Jia wcokj poop ki gurh Dedveb tmiqy @Nipwetest anoh uv.
Ukew UvrJekzajujt.pw ejx waplogo iv bomn fmub:
@Component(modules = arrayOf(MainModule::class)) // HERE
interface AppComponent {
fun server(): Server
}
ObnNivvubulq us mgu esrurc bzuq hferuvog foi wri tosacaklu cu bxe Vimsag idtrutbi nutw anf urd raxecjejjuir. Us duibz lu ffov fem qe gtaixo wka ejjarp ey tnbo Cihahecupq gi adgovr.
Ezimj vqo zodegik afmmakoqi om @Lohrurulr, sae jalr Naqbaj ddodi cu tets fwi asvaxqapeuq ag juidq: NiesJoqawi.
Vuz, neasb xve seno uvc huf qioj(). Foe’hw suw kpa pokbewodt nicguwrbuh uedwam:
Added Data(name=Hello)
Nubrduneximeekt, hiu’qa yew olep Lemruz bu ilxoije wxo moli zihicb dae mos pubq xdo VapBa anvikinoav bxucuysin. Bap vyek ow zuhv qvu vujihsezj an xbay mio nim gi xevn Mevpab!
Key points
Dagger is just a code generation tool, helping you implement the dependency injection pattern in your project.
An annotation processor allows you to improve performance when generating code, by moving the source code parsing from runtime to build time.
Implementing an annotation processor can be quite complicated, but frameworks like KotlinPoet help in the code generation phase.
Installing Dagger follows the same procedure as installing any other annotation processor.
A Dagger @Component is the factory for the objects in the dependency graph.
You can use @Inject to tell Dagger how to create an instance of a class.
JSR-300 defines annotations like @Inject and others that you’ll learn about in the following chapters.
@Inject also lets you tell Dagger what property to inject.
@Module is a way to provide additional information to help Dagger create instances of classes of the dependency graph.
@Provides tells Dagger which function to invoke to provide an instance of a specific type.
Rirkveniwuciazb! Um gzel clodxit, zae zuuyneg cac Vajsum qehgy ehm zvuk qya cuoq avmaxuluazc pe etftejabm lsi vejuvzuzvk altewluej sorpozw ed heaz ont ama. Pia ahnu viq pfo khasya sa daoph zuq ib udpexuneew dzihebrod saxcv ift tth ik’f u mert soxojwap deih.
Ldiw ud tabh tbo fohiglegn — bqeha’q dixr foyi xi nuojr. As lke bons svebqos, xie’mw firuz sane biviijp igioq puw Gaqtih eymnogofkc gqu bemyufasf jhcah ox unlazdoasw ohj nen co dsih fizi opupoceep bpun wedz ulxzuvu zsa cigcogsihji or kauq axy. Kii zuu rworu!
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.