Understanding Dagger 2
I’ve found that most of the tutorials out there explaining how Dagger works are over-complicated, even the original users guide from Google/Square it’s a bit too harsh when you don’t have a clear idea of how it works.
To be able to understand it myself I’ve created a very simple Java project with a couple of classes that explores just the surface of how Dagger works.
In this article I will explain the basic components and it is aimed for anyone who isn’t using this library but is planning to.
This is the build.gradle file for the project. We are going to use the default java plugin and junit to create a basic unit test to show how it works. Do not forget to add the dagger-compiler library (that was my first mistake).
Show me the code
In this example we are going to have two classes:
- GameData: This class provides some data required for a game session, in this case, just a string.
- GameSession: This class needs the GameData, and we will inject the dependency using Dagger, rather than passing it as a parameter or creating it inside.
Without dependency injection we would have something like this: The GameData class is created inside the GameSession. Some developers will agree that this is a bad practice, for example, you want to be able to provide a different GameData for testing and you won’t be able to do that.
Dagger will take care of injecting the new GameData() into the data variable for us, we need to tell Dagger that by using the Inject notation.
Now we need to create the classes that will define how the dependency injection will work, these are the Component and the Module.
- Module specifies all the providers of the injection, in our case, we will define a Provider that provides a new GameData().
- Component is an interface that Dagger will use to generate the code that will do the dependency injection for you.
- The GameModule has a function with the Provides annotation that tells Dagger that this function is the one that will provide the GameData.
- We also need to mark our GameModule class with the Module annotation.
- The GameComponent is an interface that defines how our inject function will be. We will use this inject function later with our GameSession, which will inject the GameData we get from the GameModule.providesGameData() function.
Now is when all the magic happens. Dagger will understand that GameSession needs a GameData, that the GameModule defines how are we providing this GameData and how we want the injection functions to look like in the GameComponent.
Using our Component
The following Unit Test shows how to inject the GameData into our newly created GameSession using the Dagger generated Component.
- DaggerGameComponent is generated by Dagger including the create() function.
- It will create a GameComponent implementation, in which we can call inject() with our GameSession.
- The inject() method will take care to inject all the defined dependencies for that object.
- Finally we can see how the session.data object has been set.
This example is a simple as it gets and misses a lot of the power functionalities that Dagger offers. As I said, this example helped me understand the basics and I hope it helped you as well.
Now that you have a basic understanding of how Dagger 2 works I recommend going back to the original documentation and trying their CoffeeMaker example. Also I recommend you to watch the following video from Jake Wharton about dependency injection with Dagger 2.
Thanks for getting this far! I hope you enjoyed this publication. If you think it was worth reading, please share it and more people will benefit from it. You can also click on the Recommend button if you are Medium user. And of course, feel free to leave your feedback!