Dagger 2 Starter Series
Part 0 - Dependency Injection Starter
Part 1 - Declaring Dependencies
Part 2 - Requesting Dependencies
Part 3 - Scoping
In the previous article, we learned about what Dagger 2 is and the two ways to provide dependencies to the object graph. This time, we will tackle the ways on how to request for dependencies (a.k.a. injection) from the object graph.
Requesting Dependencies
To request for dependencies using Dagger 2, we mainly use the @Inject
annotation which is part of the JSR-330 specification. Think of this step as a way to mark parameters or fields for injection. The steps are pretty straightforward but make sure though that Dagger knows how to supply the types that you are requesting by following the steps in the previous part of the series.
1. Via Constructor Injection
Adding @Inject
to the constructor of a class will inject and instantiate all of the constructor’s parameters. You can only annotate one constructor in a class and annotating one will also add the type itself to the object graph. With constructor injection, dependencies are injected automatically by Dagger.
2. Via Field Injection
You can also put @Inject
annotations on class fields. This is very useful if you have no access to the class’ constructor but still want to do injection. In this mode, injection is not automatically done by Dagger but has to be triggered manually via components (which we will talk about later). The fields will be null
unless injection takes place.
3. Via Method Injection
Method parameters can also be injected by annotating the method with @Inject
. This is useful if you need things to get injected only after the object is created. Take note that method injection always happens after constructor injection and field injection.
Components
Only constructor parameters and method parameters of classes with the ‘@Inject’ annotation in its constructor are injected by Dagger automatically. For fields to be injected, we need to do it manually through components. Components are objects that can deliver your dependencies from the object graph to injection targets. They also control scoping
which you will be learning next time. To be able to use components, follow the following steps:
1. Define a component interface or abstract class
Write an interface that uses the @Component
annotation. Make sure to include the modules that this component will use as well.
2. Add methods to the component interface
We need to “expose” the types that we want to be injected from the modules that we have included to the component. To do this, we need to define methods that either (A) return the type that we want or (B) accept an instance of a object whose members are injection targets. To achieve this, we must follow either one of the contracts below. We can define a mixture of both contracts in a single component.
A. Provision Methods Contract (a.k.a. return the type that I need contract)
Define a method that returns the type that we want to be injected, has a valid method name, and has no parameters.
B. Member-injection Methods Contract (a.k.a. inject dependencies to all members of my class contract)
Define a method that has a valid name, has one parameter that contains fields that are injection targets, and has void
or the parameter’s type as return type.
3. Use Dagger’s generated component to inject
After defining a component, build your project so that Dagger can generate an implementation for your component. It contains code that does the actual injection, controls instances, and other things that they don’t want us to worry about. To finally do field injection, call the methods that you have defined using an instance of the generated component class whose name uses the DaggerYourComponentName
format.
If one of the modules that you have included in your component needs another object in order to be instantiated (i.e. it has state), the create()
method will not be available. You can instead get an instance of the generated component by using the component’s builder which allows you to provide arguments to your modules as well.
We already know how to provide dependencies to the object graph and have Dagger inject dependencies that we need. With this knowledge, we can already build a basic app using Dagger as a dependency injection library. However, the way we manage dependencies is not pretty secured. In the next part of the series, we are going to solve this problem by introducing scoping.