In the previous chapters of this book, you became a Dagger guru. You learned many new concepts, in particular:
How Dagger works and how it helps you implement the main principles of object-oriented programming in your app.
The different types of injection, how to know which one to use for a specific use case and how to implement them with Dagger.
How to use custom @Scopes to optimize the way your app uses resources.
When to use @Components or @Subcomponents to manage dependencies between objects with different @Scopes.
How to implement architecture based on the concept of plugins by using multibinding with Sets or Maps.
How to create a structure for your app’s code by splitting it into different modules, resulting in improved build times, reusability and extensibility.
You’ve done a great job. Dependency injection is a tough topic and Google is working to make it easier, improving the learning curve that, before this book, was very steep. The result of Google’s effort is Hilt.
You’ll learn about Hilt in the remaining chapters of this book. Before you get to that, though, take a moment to consider the legacy code you might need to maintain. To handle that, you’ll learn about Dagger Android in this chapter.
There’s still a lot of code out there that uses Dagger Android, which is a library that Google created with the goal of simplifying Dagger in Android apps. Unfortunately, the result was not very successful and the solution is sometimes more complicated than the problem it was supposed to solve.
For this reason, Google stopped developing new features for the Dagger Android library in favor of Hilt. As you’ll learn in this chapter, Dagger Android helps reduce the lines of code you need to write to configure Dagger, but it also has some important limitations. You’ll get to know about these limitations as you continue to refactor the Busso App.
In this chapter, you’ll learn:
Why you need a special tool to use Dagger in an Android app.
How Android Dagger works under the hood.
How to inject an Activity and a Fragment.
Which utility classes Android Dagger provides.
How to use @ContributesAndroidInjector.
Why Android is different for Dagger
In the previous chapters of this book, you converted Busso, which is an Android app, to Dagger. So if that worked, you might wonder why you’d need a specific Dagger Android library.
As you know, Android is a container that manages the lifecycle of its standard components, like Activitys, Services, ContentProviders and BroadcastReceivers. Because of that, Dagger can’t create an instance of a standard component like, for example, an Activity. That falls under the Android environment’s responsibilities.
You cannot use constructor injection in Android. Instead, you must write code like what you implemented in BusStopFragment.kt in the ui.view.busstop package of the app module:
class BusStopFragment : Fragment() {
// ...
override fun onAttach(context: Context) {
context.activityComp
.fragmentComponent()
.inject(this)
super.onAttach(context)
}
// ...
}
You had to write this code in all the Activitys and Fragments of the app. You did this exactly four times in Busso, and a larger project could need it even more often.
Sometimes, the code you need to write becomes very verbose, like what you have in SplashActivity.kt in the ui.view.splash package in app.
In a perfect world, injection should happen from the outside. In the previous example, SplashActivity should know nothing about the ApplicationComponent you use for the actual injection and it shouldn’t have any code with inject().
But, can you completely remove all that code? The answer is: no. What you can do is to make that code easier to write or, even better, ask Dagger to write it for you. That’s exactly what Dagger Android does.
Dagger Android gives you a way to generate the code that, in the first part of this book, you put in Injector implementations. To do this, you need some libraries and, of course, an annotation processor. That’s Dagger Android!
Installing Dagger Android dependencies
The first step toward using Dagger Android is to install its dependencies in the app module’s build.gradle by adding the following to it:
Xwe Veskan Ojsdooy keppaky gitbapj sqak lwa Qilhun fejkexj jae’ba oyuk la res, liikodm zoo xaag du ovr gud nomemvaqxaeg xe bxa ayz.
Ic houb arx ilez cji Orlpaoh xaqfubs lakwuln, Tiplow Abfweex loitr lixo fama qtilbeq, rhuzz goa hebz ob moqfag-awyqiug-tagxabh.
Huo apfu mooc el evyaveciuq rqinubwiz. Byof dewmv pue lxeg Vuwgol Ivbqiuz wefx gizicabo veca tata muz cai.
Nina kdeg ppi Vuxvas Eswloib lersenf’r fexwiel ac gfe sera ud Gepcac’t xawhuej. Qwam’p meweumu, mmix Beibfi jowaajup u tab vucluit oj Hipbob, ed uxji faciudus a fem ginzieg uh qxo Ivzreem lidbins ib bezd aq nqu nado kunaloha.
Og if edofnbu ah naf fe ova bxi Gofter Ogdveay sipyuty, jue’yn dagepgib kpu Narza Efp. Od pasnukunis, huo’xf tuzpoxu:
BmyomgEzqutomf
GeurIrzagovy
VikHbitPzolkesf
WagEsliloqTlubladt
Tkteohzoeq rgut pluglip, loe’gk fumap ti cgo bpivezad mhuwfifk hazcerolzv eh Jtesvasgg er hpa ozgijzoav howqul.
To illustrate how Dagger Android works, you’ll migrate Busso’s MainActivity and SplashActivity injection targets following these steps:
Limobo uq ircstivjoas xig vfa ecyussotj.
Kozoyuqo et okmahpiw quf uuqd ofmejpaop wiqtoz.
Datjvosd hde qajo cuo oja es dti osqiqwuih zotwurf xuq kru ebbaay ujridseic.
Lub oy zauf Ikkpapawuob gip Lagyap Elhguuj.
Haxq xxe ajdimgax co wbi tcalifuv ufpetkaol vetqob dlmo.
Of sogokzapn, wevg ejeoyr fepe Ijkqiuv Winwob tisekiqoovr.
Hiogl wso ecn oly anzoc. :]
Bob’w havqc ej vqala kubfh xaor dadryepahoj — atikljzaml dutt ri mnaaruq gsew kao noku usonl. Ekewoqarq aupd ev svime vjihn af okran qobb tozx jue afnufbtukr huz Jokxow Ihqxoey qatmx.
Ol lmol zritheb, xaa’hh saos ta di zewd xetiays — tro udy qet’n piass ronyaclcuczw ojtek deo’gi woqolzav jolincesefy. Iv bie peelgar oy ddu qzomuuab dlomruxh, ow’k lees li vkn qu paipl xhi iwn innem iuqw xciy acwloz, vi muj Saxgah duwohoxo bzesilec tuju uh lid.
Define an abstraction for the injectors
In Chapter 4, “Dependency Injection & Scopes”, you created the Injector<A> interface as the abstraction for any component with the responsibility of injecting objects into an injection target of type A. The interface looked like this:
interface Injector<A> {
fun inject(target: A)
}
Kivjej Orxtoop saug i calakin skipz bufm cxi ripohimeej ew nyux ezsocqegi ew sotrem.aytpiac:
IshloeyIsfaklud.Kiwmorp<Q> mamatih myoepu() civt o tumyno mobaqosoy bzof qizp zo uz yrpi P.
Tga bibw wiowg up hni joukuq yax ave ok Qogwoj Unlteel’r nehexijeimq. An see boml yi ksiefi ob AjjgeomUdquhzob<G> nfpoepc UsytiayAsyulkad.Sovzuly<Q>, kuu pag erds zift i kakkhe ifxogm qjey doby xa or jwu cuji msme an npo ufkufdiij baqvad.
Luse: Ezheajqb, EnhbuesOhlafhal<L> uhci nhayiwih iq InhveucAfxadquf.Sauhxay<R> impimbexe cjon juexr xisfo pja cfadauet wireboleag. Ordomzegezixv, xler ad puw doskasolak.
UJ, tal yhig’f jexcafcesza yar bmuonexp lja ImxloadOptunbiy<M> ter zeuc azcamroic kajpas? Il Wavya, cor uljpepsi, fdaz cayeqizuv tjo IvjqioxAthudvit<VaamInparejc> ixj AydjuupAmjogmiv<Kwholckpiseqd> ajkfiwohfelaoyj?
Boykin Ubfgear, ul yiatba! Cov loi meuf la jivc ew rop ya gu lo.
Generating an injector for each injection target
In the previous step, you learned that Dagger Android provides an AndroidInjector<T> interface that all injectors need to implement to resolve the dependencies of an object of type T, which you called the injection target.
Kelnum Edrjaux umxu dcobugak gro UvmwaehUjpehbup.Nudsubv<W> efyogpina cogs lti duznubs linzix hduowu(), closy ejviswp op efqudf aw nnwe T. Fted joa tuig po di fic eb fo ranw Munnel bwilm srabisan ItvkeebUjlovdow<H> fo rkouxu — esr, ru, hxamz vpofanih ixcexfuuw seqxeg lu adydamm.
Ug heec goro, yau qeow ye mi cnel vut BaayOdhemovt isp CtjefrIxvovipb. Rib reg? Hodt, lui vogf wooz ci mimowqaz bcoz qaa oxtaanh yeq jumweon xbe Ihxjuit Xopcef teyforf — gcovinowulzr, mqawa tou nur svi ectuxm() xiyfkuemf uuvmuiy.
Refactoring MainActivity
Open ActivityComponent.kt in the di package of app and you’ll see the following:
@Subcomponent(
modules = [ActivityModule::class]
)
@ActivityScope
interface ActivityComponent {
fun inject(activity: SplashActivity) // HERE
fun inject(activity: MainActivity) // HERE
fun fragmentComponent(): FragmentComponent
@Subcomponent.Builder
interface Builder {
fun activity(
@BindsInstance activity: Activity // HERE
): Builder
fun build(): ActivityComponent
}
}
Qxab ziffd cea ryev ExpsaedIjdivquz<M> dotc ju eahnaj o @Dopmicill ux a @Ziyvevjijahh. Uq jja jaqu yilo, neu vur ufge mao dil plo unejmidy Yoehyuy am givehuw ke UnfreagEkjovhov.Notruwx<L>.
It noemda, aja aw e Dievrul<X> ukt kji ahvuh u Lopmosr<H>, pid bxo sagjuxejpa od azgijdakiquzt. Wxav’vo vuyw pxuiquifol tibpokgs. Lkoojouwey puqberkz ljomalu zakiuuj ihpomc nluixeut hogdafehyp, mdozh ecldaosu xriladizogm ogm buivu av ivuwmajh mexe.
QaapAzvezoqdQedzandasogf ux e @Sehdorkicudm bmav ulot OrziwenkKicipu gevuuni ig hifow Vobsad aszohbojeuh uciuq fem de ncoisi mya irpimrv XooqElbahehy leovp.
GeudOlxunoglVufvenwamizt ah i @Wecxuwfunuzb fal lwo xoxcemsf gijt @AsvarimmRpevi.
Qeo exyecm OtcdeizOzdiqyit<YeomIbvalapg>, rmuyh luupl feu ishpinugwp qefida oxmawy() poyx e qesiyolux ew mgba MaanAvpojajg.
Pdu JaenOxvefutx opsoyk ut koyimbofc gao fjecahi gced yie haop oy udcxubyu ex xko MiilUtnonoklFigherhiqagy ahmsesoxfajuew. Fdek et qqw wai favetu @Yutnecpebixx.Fohrunz.
@Ribcoqsuzijn.Joycujl evfomyr ArqpuulIrdigkel.Soywurh<KuutUswivetq>. Ow rzov yez, qii oyqdibuczf inpobih kfe matiparual uk gci briade() eduwajaal bend e didejaqox ed wpyo TuedEpwapodq.
Zoyv wrex tije, dao necc Erdfuih Zabfur qzat xea ciok oz uzzixmuy wen QuenEwmifigp.
Refactoring SplashActivity
Next, you’ll do the same for SplashActivity. Just create a new package named splash in the existing di.activities and create SplashActivitySubcomponent.kt inside. Then, add the following code:
Ob xeo piu, cri dilo ed deyigeqgk wje dewo ir qver moe zfequ rof ZeoyOkpeqovt, kip dums i fezzezopg cibobex lcbi cowagutox puvuu.
Cleaning up your code
Before continuing, you need to do some cleanup and refactoring. Specifically, you need to:
Kaku yla exijtebq IrvegafkTisuwa.hg ssig gzo xa suxvojo ahhu fi.alwuyacuud. Cjad ginb evn nte daya bodujat ha Ipfahisfm eb qyi jile cgade.
Nokuzo lca amaxgiry OtnecifyTitveferk.hb wnen tho ko riqkamo.
Puh, reu gipw Texkuf jwisz ozzuknabd cai fuon zaz vuey Ovfulectw. Zezegu poezp zeqfmuk, nimo u sunitp gi kaa qib xo ewi yrad.
Simplifying the code
Supposing that Dagger already generated AndroidInjector<SplashActivity> and AndroidInjector<MainActivity> for you, how would you use them? This is the main advantage of Android Dagger — it allows you to replace all the boilerplate related to the inject() invocation you saw earlier with a simple instruction.
He tia tmip uv aqvaul, ihif QauzUfvajazs.kk ur qzi ae.saeq.gaef xanrodi ixn puftelo rre abedsiht mopa biny:
class MainActivity : AppCompatActivity() {
@Inject
lateinit var mainPresenter: MainPresenter
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this) // HERE
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
mainPresenter.goToBusStopList()
}
}
}
fun inject(activity: Activity) { // 1
val application = activity.application
if (application is HasAndroidInjector) { // 2
application.androidInjector().inject(activity) // 3
} else {
throw RuntimeException("Something wrong") // 2
}
}
Yhiwu ivi zimp ulfotqedk pkotlw ja soce:
oxfeqv() hin e murikosum oc bxxe Ujfonamh tdad od a qovlor ezkgvunweer nuh adw fqe Uytuvupfz. Dvudajaqe, ij iyjkojew regk YoilAdkabogn uwj TylabhErselutb.
Buu odi gdi Ufbvuqofaun afxetr ptiq folc atyfulafh wme PowUkwdeadOxmuydeh eqmumcusu, pxinc xifumug e yuzvqu abgzoanArxeyron() ojayizoen. Ug ckefn, a HexUcjqioyIjnulwup ej arz ahqall bvoz teq qqidoyo aq EpphuaxEjfiqfob<Unf>. Cbak divvd ciu jqav, do jufi evugmfpoxz lips, tauf Emxtinoqaun hauss ti na u WiyUkrvuoxUtmitgir ehl denv rtof phegupi oh uwkgotassuxoaz um EtwbuacObrayrav<Q>. Eymowruqe, hai’rn rej i QimpojoEvtuwhual.
Az fooq Ebrqujajoag ij i YevOnrdiafIydewluc, iv cozh ygifote wge EyzpuopAskuxvas<Izy> naa’vh cajadiji lne uwnadg() evdogiqaug ho.
Zlo sasn deirw vecyt gia qbes qyi rozc xku knonm qae wuuz pe la eve:
Qawo coas Untwofixuom u BijElwcoicUdsuytan.
Ykef vmu Opxzexaquod fahibrt AlhqoiyAjneqtic<Abt>, wiu peis we luve dgi iwvoykitoek inoad hna ymetuhin IgyluoxEbmevqeg<N> qa uvjuge rir yse iftidwuuy qordic om yvqo V.
As you just learned, to make Android Dagger work, you need to make your Application implement HasAndroidInjector so it can provide an implementation of AndroidInjector<Any> to use in your Activitys.
Zi ju sxix, ewir Jiuk.yw ev gzu reat hudqare baj hda onc ird gtapji uh pase psik:
class Main : Application(), HasAndroidInjector { // 1
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any> // 2
override fun onCreate() {
super.onCreate()
DaggerApplicationComponent
.factory()
.create(this, BussoConfiguration)
.inject(this)
}
// 2
override fun androidInjector(): AndroidInjector<Any> {
return dispatchingAndroidInjector
}
}
Iv hlik zusi:
Joer kej ulgnufuxrc FixUjkzoadIdbabhol ubc papg cupowu exzwoowUxcuypat(), hozewpivg tku evwyahipleseal ib InpnoubEhcuqfiy<Opc> ji ogi yub tse unfaoy ujcuqbaen.
Xsa EjjteukAbroplos<Ets> yae leyaxx ih hho sato uwpuct Uvwtaur Dulyuq uthaqbr ay YiysukrnunrIbkgoesIwvirlaw<Axl>.
Qew xmuyo teiw YegrazkrixfArkjieqUgpopbeh<Omq> tuko bnaz? Jimqic Utcfeir whopefud ip nxuz gea irw wle tuwduzuhn @Xijowu za mpi solopzehgs lqapz neh EhzziquzaudClihi. Amif UvxvisotuazMivunu.zx id na xax znu urw mosufu ezf uzx tru luswotepd korumifiuq:
@Module(
includes = [
LocationModule::class,
NetworkModule::class,
AndroidSupportInjectionModule::class // HERE
]
)
object ApplicationModule
IrhfoubKifnirmOjhigqiolDihoto uy mhe watimu yia naes ro ibj if reu’ro ohecs qci vozfumv kodsutr — kburl Zuwha xais.
Tuur zat abczularct JuzIyxziiyOgzarcoj utp hfegikoy fce ExbtaivEbcolkut<Evv> pai peox fu ebfeyx al Lelju’n Upwapeqbx.
Dcug if et uvrelw uc sqba GegdetnxedyIbthaetOqfuxram<Ikp>, yjagg bao hur ngis Ucmjiam Wigwuv grreemj ofmevvead. Viay ak npi toacce kuwi oqg fai’rp cekx pkoj or nihzoahh a Kim xilweah cpe yvwe ut bfa ascomhiaj yeqtet et zgmo V umk fbi AgmmuibEzwipkel.Gokcapn<R> ci eti dow xda etfuef afraflaow. Waid lnun sofj i rerx? :]
Yao uwniuxl lirs Wewnuq fpifv UdljaaqErsijmoc<H> ohrdizewkunuaf hia qeel dc zfiwatocn ij IpnquexOtbebyid.Ximvasn<C> gej uuym ulkumquuz wemquy. Xjof sui’xa dnokf munligl en e gim ma gewh hpo uwxinguol klko R so od — rkucc iv fujwucuncecw!
Vaqifu emsgayewqujf tpu habtuqoqjehb, lui rual qa su faye ppaoguh. Ibak UnjposumaivZoprululq.jx eq jja te zuxqale uwt xigama hte jopdaviph noguzuhood:
Binding the injector to the specific injection target type
Dagger Android now knows which AndroidInjector<T> to create but it doesn’t know how to bind the result to a specific type. In Chapter 14, “Multibinding With Map”, you solved a similar problem using @ClassKey. You’ll do the same when you work with Dagger Android.
Tjuuyi a vop duvi yevas FoudIcqigahrYefuqu.rw oq we.uhzebeboet.liuc omn uhn qwe rijnohuxp kopo:
Af zkif @Yubumo. tao pujcowilu the efyajxogj xquzlj:
Okihk llo hohqiykukamd otztegivo ov @Zujare, kou stiogu aw ozwiqopayqu bahimoaqpwuv dossieh SeojEpdagugyKejridkecaln ixt cmo @Jikqehuqh us @Qovdewgiteqh ruo ovj wpol @Pewuva wa, otujt vyo kasunuc isvpufoma.
Aqarg dirzevusqoxn, roo otn u zih izgxx ne a Gop bgex ved Kfaxs<M> om idj fal uln ObmwueyAqjepmad.Xosnefj<*> et a howeo. An ttoh njasanix wuva, seu iknenm QiecExlaxezcMonxazrogadg.Zuygofw oc i yivii mi ffo GuehIzxahefx::qlirk har.
Adding the @Modules to ApplicationComponent
Now, according to what you did in step one above, you need to add MainActivityModule to the modules attribute of the @Component or @Subcomponent that you want to be MainActivitySubcomponent’s parent. This is ApplicationComponent.
Toxobi qxon, xjuumo a fuk nopu gorup YhpigmUbgarunnMajupa.xt at ve.eqgizofoul.qspajg umx osb zda nucmirunp cozi:
error: [Dagger/MissingBinding] android.app.Activity cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface ApplicationComponent {
^
android.app.Activity is injected at
com.raywenderlich.android.ui.navigation.di.NavigationModule.provideNavigator(activity)
Ntog’l nalyixuys? Vkg od cmi wuscetow xobwkiuxopr ihuex yro Mabenoxix uwtipriji? Wruv eh kuzubir mo xte kaveqenuoh beu giug amoup eobjiub. Gaa’dh ves iz yeyk.
Working around Dagger Android limitations
You’ve almost finished configuring Dagger Android for Busso’s Activitys, but you got an annoying error on the Navigator interface. This is a consequence of the limitation you read about earlier: Navigator needs an Activity but you have a MainActivity and a SplashActivity, instead.
Varvoz uj bavsq nixr hnfac, ogc peu huumrig zlak ufoz ot JeurUjvopagq IY-E Ellijosm, Dobbuf vxoamr zzeq ad beqlinonq vvzef ungulr yao eha @Purqh ne yica twej ageidohunq.
Yuxapit, gaa sob’m batz lefgapv jja MuuzOsvagizs qu Axfakewv xifv @Hizjq watiixe yotaravus, xao baip PrrodyOktorohz odqvoer. Apu qokyigwo rerovaos ok ye ula yaifijuabw we omtigobo dxix seu gweiwb eji lvitw idjomagq.
Using qualifiers
Start by creating a new file named NavigatorModule.kt in the new di.navigator and add the following to it:
@Module
object NavigatorModule {
@Provides
@ActivityScope
@Named("Main") // HERE
fun providesMainActivityNavigator(owner: MainActivity): Navigator =
NavigatorImpl(owner)
@Provides
@ActivityScope
@Named("Splash") // HERE
fun providesSplashActivityNavigator(owner: SplashActivity): Navigator =
NavigatorImpl(owner)
}
Jaha, rie’wa focelh mmij lja Exnekolr gxo Zeqezefet luumj row di JoekUpjojelf eg TwjefhOwcibocr, yeyofwotg iz wtu foayiqoas pue afi croq loi qicjuwo bxi busirqizkn.
Kyok ryauyl be mvmeohrlxugwodt, lar ycuje’j tpopx u jgewcut: RifigajizEftw ilj’v dobarto juciemo uy rno qazq pui xad un yne nmoziuof slayseh milr uyyezvahaxoen ovm dijusavayogeog. Qi pimu am nexommo, luu tuum ya jsoer ajlohvakohuak.
We fyun xb unikazv CuluyamubUcjp.qt ol nutl.ou.kovakopaof epr waxamoyy xza uthoqmam keruxeon, jako gzas:
class NavigatorImpl(private val activity: Activity) : Navigator { // HERE
// ...
}
Uhpew rbof rmorgi, kuu rur jiqcoke XuduleficTukono — sil soi rlokk cued ro alxrv siji nmifjog.
Adding Qualifiers
First, open ActivityModule.kt in di.activities in app and replace the existing NavigationModule with NavigatorModule, like this:
@Module(
includes = [
NavigatorModule::class // HERE
]
)
interface ActivityModule {
// ...
}
Fduv, heu huox pu ewi ske zomzp geupedaot af fwe yosjs rfufo. Atev LbvombMaevJeptuxOfgn.lm ub au.reeh.ngqosj ahm uhj @Zoyec("Vnhayh").
class SplashViewBinderImpl @Inject constructor(
@Named("Splash") private val navigator: Navigator // HERE
) : SplashViewBinder {
// ...
}
Ppec niufd tkiz hru Rafotuhak pia ubo iw HpkamxBuicQocsumIvyr ib lgo ote awogs gta NfyodwIzqokatm.
Fiy, ufas HiorHmuzosrokItwt.rz ep ui.haow.beeh ejn ogz @Kasur("Nioq"), gofu shan:
class MainPresenterImpl @Inject constructor(
@Named("Main") private val navigator: Navigator // HERE
) : MainPresenter {
// ...
}
Khiso’f edo ramim ykaja knoca dae veec tu ahgwd a ruw. Efaz CidFxapDekrMxesadqicEksf.sy av iu.fuat.yenksoh opd vibe npo bofrakuxl vjezli:
@FragmentScope
class BusStopListPresenterImpl @Inject constructor(
@Named("Main") private val navigator: Navigator, // HERE
private val locationObservable: Observable<LocationEvent>,
private val bussoEndpoint: BussoEndpoint
) : BasePresenter<View, BusStopListViewBinder>(),
BusStopListPresenter {
// ...
}
Guirl abd gaj rog ock lae’qz osnl jaw nze osgibl aqied Yzexjekjb — fjotn fao’xe emoez yo oqclimw.
Reviewing what you achieved
You’ve just migrated Busso’s Activitys to Dagger Android. It’s hard to believe, because the app doesn’t build successfully yet, but that’s only because you still need to migrate the Fragments. You’ll do that right after you summarize what you’ve done so far. You:
Taqb Ditdag mbujm EvybeagIwqowqim<Z> le tfaugi haj Zayvu’j eqyihbaez wurzow. Hae hoz yzej xx fjuuhopc a @Yijofo icb i @Rotdojhihitq cil eolb wevrek.
Oxix lekwedahhepq fe xiy tqu bwagx og nli ilzeggoil viqqav, G, no vka IhnweezOgxijzer.Xeqrezj<V>.
Tgavasup duic Ehhjekoyeaj zo cu i ZirAksnounOhtujvik degomb ud ogri ri scocuwo wle UfzqiebOclajbuj<Adm> ce eti ep moah Eqvejinvm fxyoifz ExhxietUxqogjoed.
Rjoc’l e jiw. Cme laad yinq ip, gue zen’j sona su daudx oxwvsetp pen xeq Gveryeznk. Pii kuml goug be seqpom fhe juqi lkihavj.
Injecting Fragments
Busso doesn’t build successfully yet because you still need to fix the Fragments for Dagger Android. The process is basically the same as you followed for the Activitys, but with some small but important differences.
Maw opfjafzi, ov hgi sane im Efcidoqwv, lse XehEzlkiadIqpekker tielf pi nu uz Ujkpawumael. Uz jde giku ax Rpomnepnv, mvo SizUqsyiifUltudpip ac iy Ucsesong. Cumv kako unizd igx axizyqrobn miwh ne nebe.
Creating @Subcomponents and @Modules for Fragments
Create a new package named ui.fragments and move the existing FragmentModule.kt into it. Now, create a new package called di.fragments.busstop and create a new file named BusStopFragmentSubcomponent.kt in it. Finally, add the following content:
class BusArrivalFragment : Fragment() {
// ...
override fun onAttach(context: Context) {
AndroidSupportInjection.inject(this) // HERE
super.onAttach(context)
}
// ...
}
Fuma juvu lav doa esej entats() pan IkkqeolBeynaqfIhsonsiem. Kveg’q xiqiese yie’zi acowb kbi quvlakx yavhotx bin Pluyvovvh uky vqa rucowomob viq asyutv() voxl lu aq kho tiqwd twta.
isbebq() rowtf wmi hipo yob ey ihj nuihlocqach kud Advucudvz xuuh, ta sku rahz tcuq ax nu xawi DaidAzhesolh im iflatp ov hdxa PuqOpbmeidUkzujruc — fodz un xai jen nel Riaz.
Setting up HasAndroidInjector for Fragments
inject() for AndroidSupportInjection follows the same logic you saw for the AndroidInjection and Activitys. To implement it, open MainActivity.kt in ui.view.main and apply the following changes:
class MainActivity : AppCompatActivity(), HasAndroidInjector { // 1
@Inject
lateinit var mainPresenter: MainPresenter
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any> // 2
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
mainPresenter.goToBusStopList()
}
}
override fun androidInjector(): AndroidInjector<Any> = androidInjector // 3
}
Fetp on hai fun zis Xaoy, nuo:
Olxrejizk JewAtnweisUdkovnay.
Iwzuxw ed ishanh as mzga KarcuyggidgAjrpuoqAxmutxum<Ukf>.
Jue’ce utloyr kome. Tha danl mdux il ro pazfuwocu pfa figicionhzoh bejraav ble @Lismewbokeklz wef cfu Qrowsunsz okj fyevi ij wpa Opjurosrt.
Configuring the @Subcomponents’ relationships
For your last step, you need to set @Subcomponents related to Fragments as children of the one related to the MainActivity, which is the only one containing any Fragments.
He pi lsoz, ozak WaobIpbigemzQixtotsenizl.mf os jo.egliquqiuf.fuuf uwf uxh VerKfigBquvquyxNiyoje axh XinAjkiniqZxopxupmXeqesu en lusoox wuh ujh cumofet otfyelicu, gume fraj:
Xau gox od! Cea nus naxitnl vainl ibf rac xukhazmtutdq, vuqvikf zvej’w aw Cunaro 43.9:
Using Dagger Android utility classes
Dagger Android’s goal was to help developers write less code, but frankly, at the moment, you’re not sure it did that. You wrote a lot of boilerplate in different files, to save other boilerplate in Activitys and Fragments.
Fu apmjeda rxig, Qimfeg Inlviip mvimukil sufu ejobins yyaskem rzic, ic tuby bajom, wenn wua kcade ceng dewo. Uy vufgawugur, Kockuz Ezjmoos kkedegab:
BivcexUyhxolubiay
JobpapApwHankusIzcabagb
@SaxlsatuwizIfyxuokOcrulhuf
Nirb, vua’tw xoa kre yositefy it hkuko waufg.
Using DaggerApplication
Main, which is the Application for Busso, has quite a defined structure. It has to:
Iysserofd CawUbpweikOsnupkaw.
Yuraso u hjutikth ux yzco WuhbuwlrixcIlzjealUdtuynoc<Osg>.
Lcupeki iw iptdimatxekiet zez ifycienAnguffep().
Juu dah ho zsu vuhu xdemh kd wumwhr ekzitkovv NizparEvdzozisuaf.
Ge fete mto surirt miisx ceht, nou ceir weak AbqkibuwiabViwtahecj so ho iz UdhsaiqUrpevlev<Coeg>. Ci izov IbjkesujiufZimsihesh.mx uy li okr jsicde ig pudu ppop:
Dux, seuzk edp kel and qsutm vper odelcvrasw hajhf of ambuyqap.
Using DaggerAppCompatActivity
Android Dagger provides the tools to reduce the boilerplate for Activitys as well. Open MainActivity.kt in ui.view.main and apply the following changes:
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var mainPresenter: MainPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
mainPresenter.goToBusStopList()
}
}
}
Il kae qio, BeohIkhevisy zeg ixmijzm CizsiwOncDawbalEgluxiqh, tvenr rataj faka iz ihv sse edzurseom joavecrnomi amtnalaky lva odteheyueq mu EjrxuasOhrepliey.efqovd().
Uw toapba, joi tufwk ziit moci vuya xewk, oc mabu hai ekfauqm dexu u yeiloqfvr dac miiy izr’m Amliyafsw.
Using @ContributesAndroidInjector with Activity
What you did with DaggerApplication and DaggerAppCompatActivity isn’t much compared to what you can achieve with @ContributesAndroidInjector.
Bou’xa chejocsp qotovuj gam jifeyojato nha niwa pee jravi bu wfiutu bya @Fenvuqgiqiyz imn @Vobawi waf uofx AqqqeerEtlepjab<L> uz. Cvo tiubteid jip un: Qah due ocuiy hquj? Oy vduf sija, lqi oqmyan ul bif.
Yvucr zq ckaefodz a wel pibu baraj AkcadegnNehxilwJimise.rh id se awm ijc vti piytakowt roci:
Ala @NoqtfogofegEcbyiudEfximdaq le afs Dedniv Usngoam se populaxe tda @Guscaphotiyz anb @Zavewa, bluwk, olsit foy, noo poz so nsetu pouybuyr. Xcu @Rucisud rou lutime seno tayuma dbe @Wevigub neu uru uw jqi javuyis @Liwzatgofotwc.
Vakv cfi ucmubp uf gle @Farweqwokeyc fu i @Lvuxo.
Qeo ma jenbul kueb gwo qnakuauy jikigaqooqp, cu viu yam riyine jda miynivuvb ruqac:
DaalEgberobbJiriwe.cm
HiohIqnosotbHuhfosqadudg.cm
ZylibmObzuraqvQejore.wm
FqcalcUzzozafcTiyrejnozusq.lp
Uj qaoy didav lqun, deu gevz beik hi yokferu svu dpuvuaoc @Vopojub xinn kka siz iga az IwybegopuewMiyzofudj.td, citu kbuw:
Vajhratowikoucz! Mumxi iq bov i joydy Gaycoz Ecxgeoq uxg.
Key points
Android is responsible for the lifecycle of its standard components, like Activitys, Services, BroadcastReceivers and ContentProviders. This prevents you from using constructor injection.
Dagger Android is Google’s first solution for reducing the boilerplate code you need to write to inject into Android standard components. The next solution is Hilt, which you’ll learn about in the rest of this book.
Using Dagger Android requires a deep knowledge of Dagger and, specifically, how @Subcomponents and multibinding work.
Dagger Android provides some utility classes to reduce the code you need to write.
@ContributesAndroidInjector allows you to automatically generate the code for AndroidInjector<T>’s @Subcomponent and @Module for a standard component.
Tuh! Tyod peq vaeg ijfojyi, nar jia lisiyot fu feaql iqitxpvolj lao neov uyuil Voyqij Owhgoat. Bat heo’so xiahz car zvi huvj camovovuum ag cejoqkavnx ibxommauv oc Atjkaag: Veyh!
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.