Below you will see a free translation of an article by
Miquel Beltran published on
Medium February 12, 2016. The purpose of the article is to develop an understanding of the basic mechanism of the work of
Dagger 2 .
I found that most guides explaining how
Dagger works are too complicated. Even
the Google / Square guide is too hard to understand if you don’t have a clear idea of ​​how
dependency injection works.
To understand this, I created a
very simple Java project with several classes that shows how
Dagger works.
In this article I will explain the main components of the
Dagger . The article is aimed at those who do not use this library, but plans.
')
Project structure
apply plugin: 'java' repositories { jcenter() } dependencies { testCompile 'junit:junit:4.12' compile 'com.google.dagger:dagger:2.0' compile 'com.google.dagger:dagger-compiler:2.0' }
This is the code for the
build.gradle file. Standard java plugin and
JUnit will be used to create unit tests. Do not forget to add the dagger-compiler library to the dependencies (this was my first mistake).
A note from foal regarding the dagger-compiler dependency:
For Dagger ‡ and other APT-based products, it is better to use the gradle-apt-plugin. This will make the compilation of your project more transparent and safe, since two different classpaths will not be confused - one to compile your code and the second to generate it.
Show me the code
In this example there will be two classes:
- GameData: This class provides the data needed by the GameSession class. In our case, just a string.
- GameSession: This class requires GameData . We will inject a dependency using Dagger , instead of passing the GameData parameter or creating an instance inside the GameSession .
Without dependency injection , something like the following would
turn out : the
GameData class is created inside the
GameSession . Some developers will agree that this is a bad practice. For example, if another
GameData instance is
required for testing, it will not be possible to create it.
public class GameData { public final String hello = "Hello Dagger"; }
public class GameSession { public GameData data = new GameData(); }
Dagger will take care of us
injecting the GameData instance into the
GameSession class
variable . You only need to specify this using the
@Inject
annotation.
public class GameData { public final String hello = "Hello Dagger"; }
import javax.inject.Inject; public class GameSession { @Inject public GameData data; }
Now you need to create classes that determine how dependency injection will be implemented, these are
Component and
Module .
- Module identifies all injection providers. That is, it determines the methods that specific instances will return to us for injection into the dependent class. In this case, you need to determine the supplier who will return us GameData .
- Component is the interface that Dagger will use to generate code to implement dependencies for us.
import dagger.Component; @Component(modules = GameModule.class) public interface GameComponent { void inject(GameSession obj); }
import dagger.Module; import dagger.Provides; @Module public class GameModule { @Provides GameData providesGameData() { return new GameData(); } }
- GameModule contains the annotated
@Provides
, which tells Dagger that it is one of those functions that returns an instance of GameData . - It is also necessary to note the GameModule class with the @Module annotation.
- The GameComponent interface defines the injection function. This function will be used in the GameSession class and will inject an instance of the GameData class into it , which will be returned by the GameModule.providesGameData () function.
All magic is in this moment . Dagger understands that the
GameSata class requires a
GameData class, that the
GameModule class determines how an instance of
GameData will be obtained; That it is necessary to use the
GameComponent interface to start the injection, called from the
GameSession class.
Using Component
The following unit test shows how to embed a
GameData class into an instance of a
GameSession class
created using the generated class of type
Component .
import org.junit.Test; import static org.junit.Assert.*; public class GameSessionTest { @Test public void testGameSession() { GameSession session = new GameSession(); DaggerGameComponent.create().inject(session); assertEquals("Hello Dagger", session.data.hello); } }
- The DaggerGameComponent class is generated by Dagger , including the create () function.
- This class implements the GameComponent interface in which we can call the inject () method and pass an instance of the GameSession to it .
- The inject () method takes care of embedding all dependencies for the GameSession .
- Finally, we can see that the data field of the GameSession class is set.
This example is simple; it misses a lot of
Dagger functionality. As I said, this example helped me understand the basics, and I hope that it will help you.
Now that you have a general idea of ​​how
Dagger 2 works, I recommend
going back to the original documentation and try to understand the CoffeeMaker example .