Dagger 2 for Android Beginners — Dagger 2 part II
This story is the fifth part of the series, Dagger 2 for Android Beginners. If you did not read the previous one, you can start from below.
Series Pitstops
- Dagger 2 for Android Beginners — Introduction
- Dagger 2 for Android Beginners — DI part I
- Dagger 2 for Android Beginners — DI part II
- Dagger 2 for Android Beginners — Dagger 2 part I
- Dagger 2 for Android Beginners — Dagger 2 part II (you’re here)
- Dagger 2 for Android Beginners — Dagger 2 Advanced part I
- Dagger 2 for Android Beginners — Dagger 2 Advanced part II
Previously on Dagger 2..
In the previous pitstop, we discussed on how using DI manually will complicate our work and increase boilerplate codes. We then discussed how dagger 2 will take all our pain and generate the boilerplate itself. We also ran through annotation processing basics and Dagger 2’s basic annotations. Then we applied those annotations in our example and we injected the dependencies using Dagger 2.
Note: If you’re not comfortable with the way of my storytelling — keeping Game of Thrones as the concept, feel free to change the name of the classes when you proceed.
Anatomy of DaggerBattleComponent
To understand Dagger 2 better, let’s visit the DaggerBattleComponent
class. ‘Control or Command + click’ on DaggerBattleComponent
class. You will see the following snippet.
For our previous hard dependency issue, here’s what Dagger 2 has generated for us. If you look at the interface that the class implemented — BattleComponent
— this is what we created and requested Dagger to provide us War
dependency via the method getWar()
.
This dependency is provided to us, over a builder pattern (you can learn more about the builder pattern from here and here).
It’s Playtime!
Let’s try to mess things up and learn few things. I hope you clearly understood what getWar()
method does in the class. Now, I also want a couple of other dependencies i.e. Starks
and Boltons
. Let’s create those interface methods and check.
On making the following changes, hit the build button. Now, let’s check our DaggerBattleComponent class. If you did it right, you will see the following.
If you notice the difference, Dagger 2 has overridden all the methods (getStarks()
and getBoltons()
) and it returns the right objects in place.
If you ask why and how? well, we told dagger to take those dependencies via our @Inject
annotations. Let’s mess few things now. Remove the @Inject
annotation from Boltons
class. Now, hit the build button.
Nothing happened? yeah, you might not get any error. Try running the main
of BattleOfBastards
class. You must be receiving the following error.
If you read the error, it clearly tells us that the methods getWar()
and getBoltons()
will not work if it’s not provided with @Inject
or @Provides
annotation.
So as we mentioned earlier, Dagger 2 is highly error traceable than Dagger 1 — Proves right. Feel free to play with this class.
@Module and @Provide annotations
Let’s dig more about a couple of useful annotations — @Module and @Provide annotation. You might be using these as well when your project size increases.
@Module
In short, @Module
annotation, marks the modules/classes. For example, Let’s talk in Android. We can have a module called ContextModule
and this module can provide ApplicationContext
and Context
dependencies to other classes. So we need to mark the class ContextModule
with @Module
.
@Provides
In short, @Provides
annotation marks the methods inside the modules, which provides the dependencies. For example, in the same example above, we marked ContextModule
with @Module and we need to mark methods which provide ApplicationContext
and Context
with @Provides
.
Let’s see a small example (Refer the following branch)
Example
Let’s take two services provided by the Braavos — Cash and Soldiers (I don’t know if they load money or army, let’s consider it just for the example). I’ve created two classes Cash and Soldiers.
Now, Let’s create a module called BraavosModule
, which supplies two dependencies — Cash
and Soldiers
to other classes.
As we saw earlier, We need to mark all the modules with @Module annotation and the methods which provide the dependencies with @Provides annotation.
Let’s jump to our BattleOfBastards
class and make the component implement the methods provideCash()
and provideSoldiers()
.
Also, notice that I have included the module in the component statement. This is to notify that this component includes the following module.
@Component(modules = BraavosModule.class)
After adding those, build the project again. You will see the error in .create()
of DaggerBattleComponent
. This is because, adding a module, we need to pass the module dependency to the dagger. This we need to pass it like this.
BattleComponent component = DaggerBattleComponent .builder().braavosModule(new BraavosModule(cash, soldiers)).build();
After including all the modules, you can start using the methods using the component.
component.getCash(); component.getSoldiers();
If you happend to look (Ctrl/CMD + click) at the DaggerBattleComponent
class, you will notice that the module BraavosModule
is included and derived to give us the Cash
and Soldier
dependencies.
TL;DR
We analyzed the anatomy of the generated class by the dagger and we spotted how dagger utilizes the builder pattern to deliver us the required dependencies.
We also saw a basic example of using @module
and @provides
annotation.
What’s Next?
Next, we’ll see a realtime Android example on using Dagger 2. Stay tuned!
Please do check my other stories
Thank you for using your precious time to reading this article. Liked it? Clap your 👏 to say “thanks!” and help others find this article.