.When it comes to managing dependencies in our Java and Android code, Dagger comes first in our mind. dagger is fastest dependency injector for Java and Android. In this post, I’ll give you a complete understanding of Dependency, Dependency Injection in Java or Android. I’ll share Simplest Example of Dagger1 – Dependency Injection.
Square’s Dagger 1.x is deprecated in favor of Google’s Dagger 2. Please check the migration guide for help with the upgrade.
What is Dependency & Dependency Injection:
Dependency:
When it comes to dependency, we always think something is dependent on other thing. Dependency in case of programming can be defined as one object is dependent on other object or objects. For example, we have a Computer object which is dependent on Monitor, CPU, Keyboard, Mouse object. without CPU, Keyboard, Mouse, Monitor object we can’t create the computer object. It means Monitor, CPU, Keyboard, Mouse objects are Dependencies for the Computer object.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class Computer { private Monitor monitor; private CPU cpu; private Keyboard keyboard; private Mouse mouse; public Computer(Monitor monitor, CPU cpu, Keyboard keyboard, Mouse mouse) { this.monitor = monitor; this.cpu = cpu; this.keyboard = keyboard; this.mouse = mouse; } } |
1 2 3 4 5 6 7 8 9 |
public class CPU { private String ram,harddisk, processor; public CPU(String ram, String harddisk, String processor) { this.ram = ram; this.harddisk = harddisk; this.processor = processor; } } |
1 2 3 4 |
public class Keyboard { public Keyboard() { } } |
1 2 3 4 |
public class Monitor { public Monitor() { } } |
1 2 3 4 |
public class Mouse { public Mouse() { } } |
Dependency Injection:
Now point comes Dependency Injection so According to Wikipedia, In Software Engineering, dependency injection is a technique whereby one object (or static method) supplies the dependencies of another object.
Completely, Providing dependencies to the dependent object with a technique is called Dependency Injection. For Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Computer { @Inject private Monitor monitor; @Inject private CPU cpu; @Inject private Keyboard keyboard; @Inject private Mouse mouse; public Computer() { } } |
In the above snippet, I’ve used @Inject annotation from Dagger1. Now we don’t require to pass Monitor, CPU, Keyboard, and Mouse object to computer object. All the dependencies are provided by Dagger itself.
Using Dagger1 :
In dagger, we can declare dependencies using @Inject annotation. You can add dagger1 dependency using for maven & for Gradle.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<dependencies> <dependency> <groupId>com.squareup.dagger</groupId> <artifactId>dagger</artifactId> <version>${dagger.version}</version> </dependency> <dependency> <groupId>com.squareup.dagger</groupId> <artifactId>dagger-compiler</artifactId> <version>${dagger.version}</version> <optional>true</optional> </dependency> </dependencies> |
1 2 |
// https://mvnrepository.com/artifact/com.squareup.dagger/dagger compile group: 'com.squareup.dagger', name: 'dagger', version: '1.2.5' |
Dependency Declaration:
We can declare dependencies via two ways. One via Injecting Members and other via Injecting Constructor. Dagger does not support Method Injection.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* Dependency Declaration using Constructor Inject */ public class Computer { private Monitor monitor; private CPU cpu; private Keyboard keyboard; private Mouse mouse; @Inject public Computer(Monitor monitor, CPU cpu, Keyboard keyboard, Mouse mouse) { this.monitor = monitor; this.cpu = cpu; this.keyboard = keyboard; this.mouse = mouse; } } /* Dependency Declaration using Members Inject */ public class Computer { @Inject private Monitor monitor; @Inject private CPU cpu; @Inject private Keyboard keyboard; @Inject private Mouse mouse; public Computer() { } } |
SATISFYING DEPENDENCIES:
By default, Dagger satisfies each dependency by constructing an instance of the requested type as described above. When you request Computer Object, It will obtain by calling new Computer() and setting its injectable fields. Now in Dagger, we need to create a Module class with all dependency providers as mentioned below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import dagger.Module; import dagger.Provides; @Module public class ComputerModule { @Provides Monitor provideMonitor() { return new Monitor(); } @Provides Mouse provideMouse() { return new Mouse(); } @Provides Keyboard provideKeyboard() { return new Keyboard(); } } |
Now, all the dependencies being provided through this Module Only. To provide Dependencies we use @Provides, when objects are a different type. When objects are the same type then we use @Named annotation to distinct the dependencies like in the below-mentioned example.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Provides @Named("RAM") String provideRam() { return "16 GB"; } @Provides @Named("HARD-DISK") String provideHardisk() { return "2TB"; } @Provides @Named("PROCESSORS") String provideProcessor() { return "Intel i9 Processor"; } @Provides CPU provideCpu(@Named("PROCESSORS") String processor, @Named("RAM") String ram, @Named("HARD-DISK") String harddisk) { return new CPU(ram, harddisk, processor); } |
@Named annotation is like scope which is by default in Dagger. It used to distinguish between the same kind of dependencies. Custom scopes are also used for same purpose.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
@Provides @Ram String provideRam() { return "16 GB"; } @Provides @HardDisk String provideHardisk() { return "2TB"; } @Provides @Processor String provideProcessor() { return "Intel i9 Processor"; } @Provides CPU provideCpu(@Processor String processor, @Ram String ram, @HardDisk String harddisk) { return new CPU(ram, harddisk, processor); } |
Here @Ram, @HardDisk, @Processor are custom scopes to distinguish all the String dependencies.
BUILDING THE GRAPH:
The @Inject
and @Provides
-annotated classes form a graph of objects, linked by their dependencies. Obtain this graph by calling ObjectGraph.create()
which accepts one or more modules:
1 |
ObjectGraph objectGraph = ObjectGraph.create(new ComputerModule()); |
This usually requires injecting the main class of a command line app, or the activity classes of an Android app. In our Computer example, the Computer
class is used to start dependency injection. We ask the graph to provide an injected instance of the class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import javax.inject.Inject; import dagger.ObjectGraph; public class ComputerApplication { @Inject Computer computer; public void main(String[] args) { ObjectGraph objectGraph = ObjectGraph.create(new ComputerModule()); ComputerApplication computerApp = objectGraph.get(ComputerApplication.class); // Now we don't need to initiate Computer class. We already have computer object initiated System.out.print(computer.getCpu().getRam()); } } |
Other Type of Dagger Injection:
Singletons:
Annotate an @Provides
method or injectable class with @Singleton
. The graph will use a single instance of the value for all of its clients.
1 2 3 |
@Provides @Singleton Monitor provideMonitor() { return new Monitor(); } |
The @Singleton
annotation on an injectable class also serves as documentation.
1 2 3 4 |
@Singleton class Monitor{ ... } |
QUALIFIERS:
We add a qualifier annotation. This is any annotation that itself has a @Qualifier
annotation. Here’s the declaration of @Named
, a qualifier annotation included in javax.inject
:
1 2 3 4 5 6 |
@Qualifier @Documented @Retention(RUNTIME) public @interface Named { String value() default ""; } |
STATIC INJECTION:
Warning: This feature should be used sparingly because static dependencies are difficult to test and reuse.
Dagger can inject static fields. Classes that declare static fields with @Inject
annotations must be listed as staticInjections
in a module annotation.
1 2 3 4 5 |
<span class="lit">@Module</span><span class="pun">(</span><span class="pln"> staticInjections </span><span class="pun">=</span> <span class="typ">AnyClass</span><span class="pun">.</span><span class="kwd">class</span> <span class="pun">)</span> <span class="kwd">class</span> <span class="typ">AnyModule</span> <span class="pun">{</span> <span class="pun">}</span> |
Use ObjectGraph.injectStatics()
to populate these static fields with their injected values:
1 2 |
ObjectGraph objectGraph = ObjectGraph.create(new AnyModule()); objectGraph.injectStatics(); |
I hope this tutorial will help you to understand Dependency and dependency injection using Dagger1. Dagger2 is completely different. Please note this point when using Dagger.
For More details about Dagger1, You can refer to link.