Dependency Injection (Dagger 2) Flashcards
Dagger 2
Why do we need Dependency Injection?
Dependency Injectionis build upon the concept of Inversion of Control. It 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 thenewoperator, then it cannot be used and tested independently from that class and is called ahard dependency.
The intent behind dependency injection is to decouple objects to the extent that no client code has to be changed simply because an object it depends on needs to be changed to a different one.This permits the open-closed principle.
What are the benefits of providing the dependencies from outside the class?
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.This sounds awesome to create a class that is not a specific implementation of a business logic.
What is Dagger 1 ?
A framework class called dependency container was used to analyses 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 Dagger 1.
What is the disadvantage of Dagger 1 ?
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.
What changes happen in Dagger 2 ?
This disadvantage leads to the birth of Dagger 2 forked from Square Dagger 1 by Google.
The big changes that were brought in Dagger 2 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.
What is Annotation Processor?
Annotation Processor is a way to read the compiled files during build time to generate source code files to be used in the project.
What is mode of Injection ?
Mode of Injection:
- Constructor Injection: Injecting the method parameters.
- Field Injection: Injecting the member variable (must not be private).
- Method Injection: Injecting the method parameter.
What is the Order of dependency injection according to JSR330 ?
Order of dependency injection according to JSR330 :
- Constructor
- Field
- Method
What is Dagger 2?
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.
How to define dependency providers (object providers) ?
Defining dependency providers (object providers) :
The term dependency injection context is typically used to describe the set of objects which can be injected.
In Dagger 2, classes annotated with @Module are responsible for providing objects which can be injected. Such classes can define methods annotated with @Provides. The returned objects from these methods are available for dependency injection.
Methods annotated with @Provides can also express dependencies via method parameters. These dependencies are fulfilled by Dagger 2, if possible.
How to define dependencies (object consumers) ?
Defining dependencies (object consumers) :
You use the @Inject annotation to define a dependency. If you annotate a constructor with @Inject, Dagger 2 can also use an instance of this object to fulfill dependencies. This was done to avoid the definition of lots of @Provides methods for these objects.
How to connect consumers and provider ?
Connecting consumers and providers :
The @Component is used on an interface. Such an interface is used by Dagger 2 to generate code. The base pattern for the generated class is that Dagger is used as prefix followed by the interface name. This generate class has a create method which allows configuring the objects based on the given configuration. The methods defined on the interface are available to access the generated objects.
A @Component interface defines the connection between provider of objects (modules) and the objects which expresses a dependency.
What is Limitation of Dagger ?
Limitations of Dagger :
- Dagger 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.
Why are we creating these annotations and what is @Qualifier and @Scope?
@Qualifier annotation is provided by javax inject package and is used to qualify the dependency. For example, a class can ask both, an Application Context and an Activity Context. But both these Objects will be of type Context. So, for Dagger to figure out which variable is to be provided with what, we have to explicitly specify the identifier for it.
Thus @Qualifier is used to distinguish between objects of the same type but with different instances. In the above code, we have ActivityContext and ApplicationContext so that the Context object being injected can refer to the respective Context type. DatabaseInfo is used to provide the database name in the class dependency. Since a Stringclass in being provided as a dependency, it always a good idea to qualify it so that the Dagger can explicitly resolve it.
An alternative to this is @Named annotation provided by Dagger. @Named itself is annotated with@Qualifier. With @Named we have to provide string identifier for similar class objects and this identifier is used to map the dependency of a class. We will explore the @Named at the end of this example.
@Scope is used to specify the scope in which a dependency object persists. If a class getting dependencies, have members injected with classes annotated with a scope, then each instance of that class asking for dependencies will get its own set of member variables.
What is named annotation?
Named is an advanced annotation in Dagger2. When you’ve more than one provides function with the same return type then dagger throws compile time exception. This is where named annotation comes to light. We can give a different name for each provider function so that the dagger can differentiate them while injecting. Have a look at the code for a clear idea:
@Module
class CatModule {
@Provides @Named("Death") fun provideDeathByChocoDonut(): Donut = Donut("DeathByChoco") @Provides @Named("Alive") fun provideAliveByChocoDonut(): Donut = Donut("AliveByChoco")
}
//Usage
@Inject @field:Named(“Death”) lateinit var deathBychocoDonut: Donut
@Inject @field:Named(“Alive”) lateinit var aliveBychocoDonut: Donut