Dependency Injection in Android using Dagger2
Dependency Injection needs a better understanding so let’s break the term Dependency Injection in two parts Dependency and Injection.
What is Dependency?
Consider the following Java class.
public class User {
private Database mDatabase;
public User() {
mDatabase = new Database();
}
}
In the above class, we are creating the object of class Database inside the constructor of class User. So here, we can say that the User is dependent on the Database. So here, the Database is a dependency for the class User.
What is Injection?
As we saw the User is Dependent on the Database, now think about how the User can get its dependency, which is the Database.
We can consider the following two ways
Method #1
Create a Database object inside the User Constructor. That is exactly, what we are doing in the above code.
It is a bad idea. We should keep the classes as independent from other classes. Now you ask WHY?
- If the classes are independent, you can reuse them.
- For unit tests in each class, it is necessary that the classes are independent of each other.
Method #2
Instead of using new to instantiate the Database inside the User’s constructor, we can pass the Database as an argument to the User’s constructor.
public class User {
private Database mDatabase;
public User(Database database){
this.mDatabase = database;
}
}
So this is what we can call Dependency Injection. It means providing dependencies from outside the class. And more specifically for the above code, we can consider it as a Constructor Injection.
Now if we want to unit test the above class we can pass a dummy object of the class Database to the constructor.
Now we have an idea “What is Dependency Injection?”
Dependency Injection
Dependency Injection is a design pattern. The general concept behind dependency injection is called “Inversion of Control”. According to this concept, a class should not configure its dependencies statically but should be configured from the outside.
How Does Dependency Injection Work?
Mostly dependency injectors rely on reflection to create and inject dependencies. Reflection is good but it’s very slow and time-consuming. Also, it performs dependency resolution at runtime which leads to unexpected errors and crashes the application.
On the other hand, some injectors use a pre-compiler which creates all the classes it needs to work using the Annotation Processor.
An Annotation Processor is a way to read the compiled files during build time to generate class files to be used in the project. So it performs dependency resolution before the application runs to avoid unexpected errors.
But, our topic was Android Dependency Injection.
By Android Dependency Injection, here we mean that using the same Dependency Injection pattern while developing Android apps.
Popular Android Dependency Injection Frameworks
- Spring
- Guice (Roboguice)
- Dagger
1. Spring:
Its approach was to use XML to do this. The downside to this was that the XML was almost as verbose as writing the code by hand and also the validation of it was done at runtime which is not configurable for Android apps.
2. Guice (Roboguice):
Guice was really the next evolution after Spring. Guice got rid of the XML configuration files and did all of its configurations in Java using annotations such as inject and provides.
But there were still some problems. Debugging and tracking down errors with applications built using Guice could be somewhat difficult.
Additionally, it still did runtime validation of the dependency which is fine for server-side applications but can be quite expensive for mobile applications that are launched much more often on devices with much lower performance.
3. Dagger:
Guice was a big step forward it didn’t solve all the problems and its design was also not ideally suited for use on mobile devices. With that in mind, a team of developers at a company called Square developed Dagger.
As a brief history, Dagger was created back in 2012 by a few developers at Square, who liked the idea of dependency injection in Java and found Guice to be very slow for their liking. As a result, an API similar to that of Guice, but provided better performance and more flexibility.
However, together with the advantages, there were many problems that could not be fixed because they were problem architecture:
- Graph composition at runtime which hurts performance
- Hard to configure ProGuard with generated code.
- Ugly generated code
As a result, together with the original creators at Square and the core libraries team at Google (creators of Guava) brought out the next iteration of Dagger, which is called Dagger 2.0
The new version, as promised, addresses many of the problems of the Dagger 1:
- ProGuard works with no configuration at all
- Improves performance, including the per-request cases (around 13% faster in Google’s search products)
- Better generated code and no reflection help make the code readable and easy to follow
Dagger 2.0
Dagger 2.0 tries to create the dependency graph at compile time hence any violation of dependency can easily be identified at compile time. Following are the types of dependency that it provides:
- Constructor injection
- Method injection
- Field injection
Benefits of Dagger 2
- Easy access to shared implementations.
- Easy settings of complex dependencies. Big apps usually have a lot of dependencies. Dagger 2 allows you to control all dependencies easily.
- Easy unit testing and integration testing.
- Code generation. The received code is clear and available for debugging.
- Code reusability
Annotations of Dagger 2
- @Module: which contains methods/classes that will provide dependencies.
- @Provides: methods that provide dependency.
- @Component: which contains all the modules that have to be used and in which classes this dependency injection should work.
- @Inject: who accepts the object provided by the @Provides.
- @Scope: enables the creation of global and local singletons.
- @Qualifier: If different objects of the same type are necessary.
Conclusion
In this article, you learned what dependency injection is and understood the distinction framework of dependency injection. Also, we learned which annotations are used in Dagger and the benefits of dependency injection.
That’s all for now, thanks for reading.