Android Dependency Injection: Dagger2

Md. Tanvir Hossain
Oceanize Lab Geeks
Published in
3 min readSep 29, 2017

Dependency Injection is build upon the concept of Inversion of Control. Which says that a class should get its dependencies from outside. In simple words, no class should instantiate another class but should get the instances from a configuration class.

If a java class creates an instance of another class via the new operator, then it cannot be used and tested independently from that class and is called a hard dependency.

The most important advantage is that it increases the possibility of reusing the class and to be able to test them independent of other classes.

Lets see an example

public class A {

private B b;

public A(B b) {

this.b = b;

}

}

this is a dependency injection at its core! Rather than creating the b object in the A constructor, the b object is passed into or injected into A‘s constructor. The responsibility for configuring b is elsewhere, and the A class is simply a consumer of the B class.

Dependency Injection

The Dependency Inversion Principle

Dependency injection is often discussed in conjunction with one of the five SOLID principles of Object-Oriented Design: the Dependency Inversion principle.

The gist of the Dependency Inversion principle is that it is important to depend on abstractions rather than concrete implementations.

In the simple example above, this means changing B to a Java interface rather than a Java class. With this change, many different types of concrete B type objects that adhere to the B interface can be passed into the A constructor. This presents several key benefits:

1.Allows for the A class to be tested with various kinds of B objects.

2.Mock B objects can be used as needed in certain test scenarios.

3.Testing of A is independent of the implementation of B.

While often discussed together, dependency injection and the Dependency Inversion principle are not the same. Essentially, dependency injection is a technique that is used as part of adhering to the Dependency Inversion Principle.

Dagger 1

A framework class called dependency container was used to analyzes the dependencies of a class. With this analysis, it was able to create an instance of the class and inject the objects into the defined dependencies via Java Reflections. This eliminated the hard dependencies. That way the class could be tested in isolation, ex. by using mock objects. This was Dagger1.

Main disadvantages of this process were two folds. First, the Reflection is slow in itself and second, it used to perform dependency resolution at runtime, leading to unexpected crashes.

This lead to the birth of Dagger2 forked from Square Dagger1 by Google.

Dagger 2

The big changes that were brought in Dagger2 were generating the dependency graph using annotation processor. The classes providing the dependencies were now generated at build time using javax inject package. This facilitated the possible error checking before the application runs. The generated code is highly readable as if written by hand.

Annotation Processor is a way to read the compiled files during build time to generate source code files to be used in the project.

So,Dagger 2 is dependency injection framework. It is based on the Java Specification Request (JSR) 330. It uses code generation and is based on annotations. The generated code is very relatively easy to read and debug.

Dagger 2 uses the following annotations:

@Module and @Provides: define classes and methods which provide dependencies

@Inject: request dependencies. Can be used on a constructor, a field, or a method

@Component: enable selected modules and used for performing dependency injection

Dagger 2 uses generated code to access the fields and not reflection. Therefore it is not allowed to use private fields for field injection.

Limitations of Dagger2:

Dagger2 does not inject fields automatically.

It cannot inject private fields.

If you want to use field injection you have to define a method in your @Component annotated interface which takes the instance of the class into which you want to inject the member variable.

In the next article we will see a solid example of Dagger 2 and how Dependency Injection works.

--

--