Greater Noida, Uttar Pradesh, India
+919990001443
rahul@shuklarahul.co.in

Dependency Injection with Dagger 2 on Android

Rahul Shukla

Dependency Injection with Dagger 2 on Android

Dependency Injection: The Dagger 2

Dependency Injection with Dagger is going really hot these days. The ease of writing code and the simplicity of Dagger is luring everyone to use Dagger in their application. There are a lot of tutorials that talk about Dependency injection, Dagger 2 usage, examples and tutorials. These tutorial tend to mix up the entire Dagger functionality into just one, making it confusing instead. This is my attempt to take it to step by step by understanding one functionality at a time.

1) Defining Dependencies

For Dagger to work, we need to tell the set of dependencies we want it to inject. This is the primary step. To achieve this, Dagger defines the annotation @Inject, which specifies:

  1. The member variable following the @Inject annotation needs to be injected by Dagger 2
  2. The member function or method needs this dependency (except constructor)
  3. The constructor injection

I will cover each scenario one by one to avoid any confusion. Lets first take a look at the constructor injection. This is the simplest one to understand!

Consider the below example:

class Dial {
public Dial() {
}
}

class Strap {
public Strap() {
}
}

class Watch{

/**The watch dial**/
private Dial watchDial;

///ToDo: The watch also needs a Strap. That is removed for simplicity

@Inject
Watch(Dial d){
this.watchDial = d;
}

public void printWatch() {
Log.e("Watch", "This is a watch");
}
}

What are we specifying here is:
1. The watch object depends upon Dial and Strap [Strap removed for simplicity]
2. To construct a watch, the Dial [and Strap] argument(s) must be provided in its constructor.

The @Inject annotation on a constructor has two different meanings:
1. First, it specifies that the dependency injection framework should supply the Dial [and Strap] arguments to this constructor
2. Second, this Watch constructor is now a participant in the dependency graph. This means, if any class has a dependency on Watch object, the Dagger 2 framework will use this constructor to fulfil the dependency. [We will cover this later on]
3. It must be noted that there can be only ONE constructor with @Inject annotation.

Well done! We have successfully defined the dependencies for the Watch class. Now the second step is to let Dagger know how to build dependencies.

2) Providing Dependencies

To build an object having specified dependencies, the Dagger must first provide these dependencies to the dependent constructor. Dagger can’t do it on its own. We need to tell Dagger where and how to get these dependencies. Dagger provides @Module and @Provides annotations for this. Let’s see the function of each:

@Provides: This annotation says, “Use this function to generate a type of dependency”
@Module: All the functions annotated with @Provides are clubbed under the class annotated with @Module.

Let’s declare our function to provide the Dial dependency to our watch object:

/**
This function will be called whenever Dagger needs to provide Dial() object as an dependency.
**/
@Provides
public Dial provideDial() {
return new Dial();
}

Now, let’s encapsulate this provideDial() function to a module, called DialModule:

@Module
class DialModule{
@Provides
public Dial provideDial() {
return new Dial();
}
}

That’s all! Now Dagger knows, how to build Dial object for someone needing it as a dependency!

3) Bake it All

We now know how to:
1. Define injectable dependencies by Dagger
2. Provide methods for Dagger to generate these dependencies.

The final step in the process is to put all this stuff together and see how to build Watch object without actually calling constructor by yourself. The key here is to provide an Interface, which Dagger 2 uses to generate an implementation and provide the Watch object. This interface is annotated with @Component, which comprises of Module(s), in this case, our DialModule. Here is how we declare this Component:

@Component(modules = {DialModule.class})
public interface WatchComponent {
Watch getWatch();
}

Dagger generates an implementation of this interface named DaggerWatchComponent, which can be used to instantiate Watch object without manually calling the Watch constructor. Here’s the code explaining it:

WatchComponent watchComponent = DaggerWatchComponent.builder().dialModule(
new DialModule())
.build();

Watch theWatch = watchComponent.getWatch();
theWatch.printWatch();

Note that the WatchComponent is instantiated through the Builder pattern and is provided with the DialModule implementation.

That’s all. We can now use this component to generate as many as Watch objects required.

The example presented here is pretty simple. As an exercise, try modifying the Watch(Dial d) constructor to accept a Strap parameter too, provide the implementation for StrapModule, modify the WatchComponent and see if you can instantiate the Watch object.

You can also download the complete Android code from the GitHub: https://github.com/trivalent/DaggerBlogOne

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.