Dagger 2 for Android Beginners — Dagger 2 part II

Hari Vignesh Jayapalan
5 min readDec 16, 2017

--

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

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.

--

--

Hari Vignesh Jayapalan

Android Dev at WeTransfer| ex Backbase | #1 Google AAD | Public Speaker | Blogger | Creative Coder & Logical Designer