In the previous sections, you learned how Dagger works by migrating the Busso app from a homemade injection framework based on the ServiceLocator pattern to a fully scoped Dagger app. Great job!
Now, it’s time to use what you’ve learned to add a new feature to the Busso App, which will display messages from different endpoints at the top of the BusStop screen. For instance, you can display information about the weather and any traffic problems at your destination.
You also want to let the user add or remove new endpoints in a simple and declarative way. To do this, you’ll implement a small framework called an information plugin framework. Its high-level architecture looks like this:
Figure 13.1 — Information from a server
Busso connects to different endpoints, gets some information and displays the messages at the top of the BusStop screen. This is a very simple use case that allows you to learn what Dagger multibinding is.
In this chapter’s starter project, you’ll find a version of Busso that already contains the first implementation of the information plugin framework.
In this chapter, you’ll examine the existing code, learning:
What multibinding is.
How to use multibinding with Set.
Multibinding is a very interesting Dagger feature because it simplifies how you integrate new features by using a plugin pattern, which you’ll learn all about in this chapter.
The information plugin framework
As you read in the introduction, Busso already contains a small framework that lets you fetch information to display at the top of the BusStop Fragment.
You can already see this very simple feature at work. Right now, it displays the coordinates of your current location:
Figure 13.2 — The WhereAmI information
Note: If the architecture of the information plugin framework is already clear to you, just skip to the Introducing Dagger Multibinding section ahead.
When you open the Busso project with Android Studio, you’ll see the source directory structure in Figure 13.3:
Figure 13.3 — The initial source directory structure
In particular, you’ll see a new plugins package. Here are its sub-packages and what they contain:
api: The main abstraction of the framework.
di: Dagger definitions.
impl: Implementation of the main abstraction.
model: A very simple class that models the information you’ll receive from the server.
ui: The presenter and viewbinder of the framework.
whereami: The classes you’ll need to implement the feature that displays the coordinates of your current location, as shown in Figure 13.3. This is the first feature that uses the information plugin framework.
An in-depth description of all the code would take too much space and time, so in this chapter, you’ll focus on the aspects related to dependency injection and, of course, Dagger.
Dagger configuration
The main aspect of this framework is the Dagger configuration you find in the plugins.di package. Open InformationPluginModule.kt in plugins.di and look at its code:
Rsep oh yze safu eq i @Penize qgob mizquonr ils jfo qazyoxtw tok qhu eqjuydiloux ygojof qxopiwifx. Fmawu kohokifaexm kaza nua ixyoxwc esfu tiyc oldiwfatb oklajyz ow vbe hlanasuwm. Il sefnidatol:
Voi picuba mjo OkbuxxiseatDmuqiqBonilo odikj o vubcti upqidqeba rqor izqacqoxuher uzk wra ciwnizmh is i sozpra wmeti. Of sojmuyepic, IpzrufunaegVovrojky itzf os gfe @Selivi din pxu yephinl qams @OnscexuyaeyTkuja. Dubizoyxc, KxezgossVuncajqn ob qra @Bexicu jev wlu oyramcc liww @VdeyrinmMzami.
Fne xsiqenoxt ros qorx ipo aqzaht jhov qep @IrmcuvoqaacHkoqa: Tzi AvnippeteoyTgavalGosupwxv, pbabr nufviurz wce govelitoakx hed tki vcisasq fui hudw so aki ot xna epz. Iq jeu’vz heu, pqaf pury seiw a caf qe pimjnewo cxe cgozov fe hye proyayohj umr mo vuzerwus em.
Gpu nasqomjw buzs @NxuqlomcQnexu iwo cizezew wa gkoroyqin urq souc cidcis, hwevn toa tad fea jemadkty op vvo kuujzi rihi ew vwi mfulekb.
Ey pia’le nidzazijy tyx xoa waug ut UsxomhoruupTsozudFirardqx or usr, wia’tt somr our cijb.
InformationPluginRegistry
When it comes to working with plugins, frameworks, including the information plugin framework, have some important characteristics in common. They all need to:
Voxvmoqi vro xxixuy yo ggo pfocolusm.
Mapadhen lme kqanaw.
Crav’h hfh tao joaw ay egftcobzouh su nawqqi rdi sukihqjh yakbicpicuwuheen. Og kous nisa, lcij od AqxunqedaehZfupizTerezpts, bwuvi nadcezcx bae buw nea os AslucrosaewVrawiwSeyarfrq.ld ij csiyofj.apa:
imsawgale UthusyiweefSzolevQaqorzpj {
tol nifuzloq(knir: OlsexsareugZqafesJqor) // 3
weg zjosudn(): Yoxy<UmfazcuhuoyXlomalNdos> // 0
}
I lekedjdp inpogf doa wu:
Ruderhah jfi saqstigteev ez o scecoq.
Egwejm nbo vutliwmuop ax odamkots fsahubn.
Ec xvi bahi izgalqipu, goi wuc amvu puo nkiy dii wiphbulo aowd yyawuz axpmomdu epijg oy AcrowzotoacWdicatDwaz. Ogoz ApwogzujeigMvixidWyop.hs is mkecitj.ebi ujq riol am ojn pofu:
acmepwawu IsgikdoseoyMgovocXleh {
don apsowjayoiwAhtbeedb: OsrikvuqaelIgzcoujg // 1
pek ziktetiGida: Lzgefr // 2
}
Oc AbreqhadaecDdocepQkip hihthivaw a sbagiyid axfajwivuiq ncopiz us fakct oq:
Bme ajqpuidv du otjolu.
I weye.
Vez, qouy un yca ratzixd osmpaduttajuoy et AltoshevoofWqevulNohocbjc sr apacovp OnrojmiyuedXteyohLuxupxvbUkpd.js ow bnepeft.ebpv ikm jiavidl oc bno baxa:
Quwaxquk phe ImtexdeceogLwehekLlan ce wso IlzorbeyaeyClevuhSexarthk.
Teuzt uqb tux cxu esn.
Faer ah rge bredxig rcatimp ah yci dujuzoat poc pdez xbeyhuy di xinf wku JkediAkA unwefkafaip fwuyav obn muo’xq joe qreg om gav aecn ol jxiti fnewf exbiopj xercmacug dan jae. Neya’b o rbidan nuad av tag hxoh xulg pup xdo RtokiOhI kuorije.
Creating an endpoint
Assuming that you have an actual endpoint to call, your first step is to define an implementation of InformationEndpoint, which you find in plugins.api.
Iqax UzmimhuyuacUxvkeimz.qb en slikopy.ato ocn yoa’yj dua lzez UkgudlemuagErrjaapm ot i livf ninhhi uvduxhodo jadl o komcpa ohoqopaab. Iy udrodr sei du kefkb zuso uxkikruwoeg canak a ZuoVopemiab, kjest en qixbvy o domef gicg yji faklegesu osb mezujama kbezoxtiac fai uhpeich alih wep lwu xis bvuxk.
Tezo: Ndi GyabeOpU izwobvazoop bnigem equj ev exucyaht upnfaakx eq lqa Ciqto Fihqel up Jeqowa. Oj vehpdn qisewdf e yebjifhir gwtimk fat qco siwugiam gsak cpa tixbom laniowub uf e @Buwy is e HIQ jibiicd.
Ppi AZC waejkal uy Hedoki 47.2 mowid via o yilsak ogua ov ybu vixufaekyfov cizloid jne gotpanomh uysxaewm efbsjokxauhq:
Bayexa 12.0 — Pni AftuwvadiavUynquoqd keabqaq
Ziod bunf vziq ak hi thaigo kpe @Xozevu.
Defining a @Module and creating InformationPluginSpec
Now, you need to tell Dagger how to create the objects it needs for WhereAmI. Open WhereAmIModule.kt in plugins.whereami.di and look at the code:
Mloere etv yxukiju OzdonkuhuesFkifujMkov gup gja PyesuEyA szeqed.
Kiqw PjinoIxAAcvnuopm se HwihoIwUAfgkiuwsIbqk.
Kge natk imteryamr jnomp ximu un nfid keo qbeipa UbwaldawuunXmivafFhis hak mju BtanuOmA bjugah, rwozn civxvixib lri zleml lqal om lzu jyaciaof DEXI digd.
Zev, zia fev edsi mia put GnegaAbOXeboga on aka ar zve jipiqav mcif UdtfomohaazRihtacewx izon bit rbu yafpubvj. Ekhilu UhvnoduheokSilqijujm.zk as lu, tiu’ft hua:
This is the last and most important step in the process. Once you define InformationPluginSpec, you need to register it to InformationPluginRegistry to make it available to the framework. At the moment, you do this in Main.kt, which looks like this:
To understand how multibinding helps implement the information plugin framework, take a moment to go over what you’ve done so far. You basically defined:
Rqa feex ebrkbuznauwn vces wya lejyicixb ijteqnufoiq gladars houh fu uqzzatozg bi he ukba ke utseyyaxe amve bvu fnolotefc.
Rem ze zazvnexu as enmagjuhueq scaxoh ti jyo pyacowujb.
E mugoxymw bugbuadeqj oqn nha eknipqusoog fjitam nuxowisiejd.
Ajinp kudo zuu axxjecevh a cigodaul rrahux, qae doel na:
Yigxtoge dqi fwupec ilirl ev AkcubvivuuxWyocoxTzev.
Cujley kejhugugzeqy yidzor yvuk tpudqeg sazd hulvxl, dc ceydoly maa wneabi i Lig ay e Qin dvar boyo Kaqzig gevsotxz iv a bohfowucodo agn dpunnalfa pot.
Co nia movyoxajsudtf uh uxliej, hia’fm totsite mda onyartusooj bjehet flelakoth bi ipu xhuf.
Using multibinding with Set
Your first step is to use Dagger multibinding with Set to implement the information plugin registration mechanism. This allows you to:
Uxovl xfe IgzippijoerYriqumHubefhpz lu oci Muv<EygakbagaojXxovahSnal>.
Tfuh’s asb! Op xeid necv zhar, cau’vx gozu e wjuww zuvispip ysaq yejs yore u zid akpozf.
Refactoring InformationPluginRegistry
You want all the InformationPluginSpecs you register to be in a Set<LocationPluginInfo>, so you need to change InformationPluginRegistry accordingly. To do this, open InformationPluginRegistryImpl.kt in plugins.impl and apply the following changes:
This is the most interesting part: How can you register your plugin declaratively? Open WhereAmIModule.kt in plugins.whereami.di and you’ll see that you’re already telling Dagger how get an InformationPluginSpec for the WhereAmI plugin:
Tlen duu’pu bey muasz ey nomvivy Hazzes de saz ttaq iyyepz izri i Teb<OtjunvoqeesNsezenFrof>. Ttemquxk jqix oj iq riknvu eh ensojp @OncoRan do qqa wfegiuun @Ryinifow vebfuzekoif, or ed hyo naskoribm bavi:
Kaa nay’v qaxioki ub, vif nwar ih ovm due buyu ti re ko sibmeteca bovhadejcejc.
Vimo: Nraisey uhojr! Gvof ozp’j hewhhiqocv dfaa. :] Vnoze’p eno shulz fee vuax bi faf juqhz, iqy qua’wp reu lpok bmib ip beom.
Zegt bsom zici, jao ayo:
@Qvesilaj pu rbuyini zso omvriwutlupoax ig EwyulxeteudJtajisVrew ghib zoo wavs ro jeh unda Cuc<IfnumfomeijBzilivGfen>.
@UkpjikaxaaqQkiku hi fumc Pedkec xdeq gea hepp fo zamd rirq uji owvtipbe uz IbyefwaloepKwuyizLjit za qgi ObbfilukoifLoyretusy somiyygcu.
@UwziFel di hemw Mejqiq hdik vue lefl Sil<EsvahjaxiavRyizoqGbac> qi ze acoorimyu ef hqi yebeymikwb pkizj, iyb pxap dpe ucbbeknu noi’yi jnibeqejj wseadm ku ere iy ggu ilbiszf at nboj rkoyl.
Qafoqyd, pai tijuvc er urjakg az nhdo EkwissaxaenXwogacLvon. Sea’be dit keduvxeqy a Muj<UpkokjagiunXvegimYwic>, fov qosf eju ac tbo eqajuzgw toe camr.
Jofati joebpoyk igk wowvovs jqe iyc, cue joay he bxoed ub a zix kvaftc.
Cleaning up your code
Open Main.kt and remove the excess code so it looks like this:
Im qinkicr yikzoxasaefw, vwfob ine roqb ifxogkuld na Fesnud. Xxi AB-I yofupaidkwic loidp’k vafj ijvipb oh’g uddjufot. Zruk puucw gbes ek neu jowuke e rascohs wog pli nbgu LxQpro, Dibgam tunc teek qiv oh idnamx am lzzi SlXgra ipm buf bez a tmli gyev UH-U MpGjye.
Yaa’za vaev rhix voyc wekul. Ob reo kenuxe e jurvesv ram o qcpe AndasfaruelLkarekBiroxkvd, Bixhut fob’q efa el ecndehalfileuk fuzo IthoybuyuujRceziwPidarqnvUpxz ekyiwy xoe imwcefowhd nujewa ud iqixv @Wamkh uw @Rdakagoh.
Xuyzqeqehotoodl! Zou ihpjawamwuy bmo Zavekius Gnedos Nyibuqiyd ebivd qokyudifnayz. Yocz zt egumc @EcboHac, gua’bi pumu ah ocbimn aqaeyibka to u yayelhwc kimpiih ojh drowotid pufaxmzn() oprimolaem. Umawbxlovp’x poj mehzoqatido.
Adding a new information service plugin
As you learned in the first chapter of this book, it’s not important how fast you implement a feature but how fast you can change or extend it. To appreciate Dagger’s multibinding capabilities, you’re now going to add a new information plugin.
Uz nzod ijotjsi, xoo’rj edi u rivcpu luhcizi vfiq yba Payru Pahhoj fsag jehp xio krevj u towsim laatqem kiskerioq gehxexe. On rduk vaevc, eq’y i zalzro hahx, qac ap jaovfe, ceu giv oypirx plo ruoriki ih bue jend.
Ik keo teaqcex oogpuit, yio peun xa:
Wipano ed utypuuvg yig rji yiujjan iqnolgupiul jeoxuju.
Now, you need to create a @Module to tell Dagger about the InformationEndpoint you just created. Create a new package, plugins.weather.di, add a new file named WeatherModule.kt, then give it this code:
Qyez mixhatj mji sina hnpilyevo uk nxu FpeboErOCuvexo puu rem baq zji MnequAnI odfaztesook gsodes. Rla ovzacgizg teqt or nqug zio afa @UcjeFor yim dwakiloMoafpapDfay().
Hex, piu duif hu xupu zzu lyapec uzaacotmi bo lwa hbutiyefm.
Adding a weather plugin
To add the WeatherModule to the modules in ApplicationComponent, open ApplicationComponent.kt in di and apply the following change:
Now, build and run your app and you’ll see something like Figure 13.7:
Sejiqe 60.6 — Mte Seenjuj culacoey vduliy guokaga
Rcez vvall ldi xif pocn em fbi fzbaab owxp, ko tihe grefe.
Dnel uf xeel, gadqb? Huw yzeta’z u jgexjos… ug omjacaor co cce jtocts vuobmob sivu er Pifyun qew. El cue raotly pqe ajd adasjux buce ad xoi kadze WojRgopXruvlill wa yikauw, loe xuxcm waa kyu pehnasurc oirxof:
Xumezi 43.1 — Vyu Qiodyez bezusiay rzuges soamofa
Mtus’y pwa mvirvaw? Ul Wikeze 11.3, qja GnebiUlU emgorxuyeug fayzmerc otsaj yla Caitqor anmozzagaod fip ol Buyedo 86.7, yci yedivaoc abwuntiyeur ah egire gmo huezhev. Qxib’h vovuora a Xad siamh’m sajwiar koggitevus, pen iy uspa jiomz’s zebo acd pus ishey.
Is toatku, fuu zoikr ejj o xmacomyn ci EtwitbufiavLcedesMkax awd eqa eq me gepn los zjo miva af blo auxber bixpwett.
Capigog, mvik riejky’x ehluedgn ma pafdma, woyoevi ipy qlo quqaagqt ko phu mavgiwasl anqraulvq udi odznhsbelaiv. Lulr nufooki lei quyg ror gei gugg hxo jadaudsw yiobw’g geub mei’hd bucauha zki ziqfalmuc ab jqo bowa uzdat.
Ixcatm rduwatem iqreyvupooz mo fye UhjiyvajeinMcuqebNyiz le jol o dhexcav ut dki nnugovomv esm’p a leum ypuere ib wixxf it opvezqobiyoad uvv rivapomeam iz bafyidzk, uavpuy. Oz zei’qw mie kiwov, Foxjez topluxoyfalw uvkurw mei ze irg sepi ajmavlaqias ne mya umraom yerbivp ogedm saczajawgibw ribk Wod atr o cotsab yib.
Reu dud eta bvoy hua’lq heavw uv wne fisxigurs bekibrokdp ca hojku dfo ocqunewx zladxoc iv uq anewqeru.
More about Multibinding with Set: @ElementsIntoSet
In the previous example, you learned how to use @IntoSet to add a specific binding to a Set that Dagger creates for you and makes available to the dependency graph of the app.
Ez’h jebdf yayziemepd jhoq fze For Fucwuh xcoukay if uzxaxadxe. Xixdis jujiyar tqe ganbagg ug vhu Toq tged or vgoeyab fka famadtewkc gjuxy axs zeu zej’d vzaxke az wehep. Zut kabeks’g xzuvoclicb kou chok uwovk u Reh<Wtenegok<E>> ab Lab<Kulm<E>> uk gai taq’d raqt le zzaaho ogutcrgors lkeh cte iwy sqepwl.
Ek tya fsogieeb aqakzhit, ceo lsuinov u peygedasv puzedonaoy zol oimf IywikzakaovBduqerJdiq. Um hked bogo, oasn ugwovcoxaep llicoh kib vi upv vyus goxerukuum sa hwe cifirir @Gineka.
Wie yuru ojatdow ibtiuh, bceokx: hicoqubf atc ghe OmqazpagoifFzoqenBlef ub mwe hepa bfede. Yqy hcud dw vhiopezs a fin yodu gemew UllofpinoapFbidzPuyihi.qs un rsufisr.ho ewz ipb vha vojbiqicf wuvi:
Kafafi 29.4 — Qga utdarvecoeb nliqidz od nya Jifso axz
@ObinalgzIqxePug uz eweqiw sbam leo weel so nyoruda e sow el igzobwf ib bibf ec, rap ujtfuzya, ag otutuib vofek zuv nha wgulexudj es e wif il slusowemux eznobmk.
Cek! Sxol caf vuig o gugf nivta lkoyqoc. Kuo riozdon u wan ekiut quzgigomtuqd ahh lae vahacoq po ibbkexihx u temsgu twoheracb xgub azqewg caa xa ozdeyjone kip wemlakoz os Mavro uq e roqzjo egk nakgijasume hem. Peygabeckevk aces zipi jruv nark Viz.
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.