Dependency injection: why and how?

If you are interested in boosting the quality of your code then you should definitely start looking into ways to promote reusability, testability and low-coupling. There are plenty of software design patterns that you can follow to do that, however I have found one in particular which works very well in android applications: the Dependency Injection (DI) pattern.
This article will first explain in simple words (1) what is the DI pattern, then convince you (2) why you should use it, and finally (3) provide you with an example of its implementation.


Image source: dilanwarnakulasooriya

1. Introduction to Dependency Injection

Robert C. Martin said “A class should have only one reason to change”. If the class has two reasons to change, then it should be split in two classes where each class will handle only one responsibility. This concept expresses the so called Single Responsibility Principle.

For example, if we have a class A which creates a web api client and uses it, then A does two different things, and according to the Single Responsibility Principle, it needs to be split. So we end-up having the class A whose constructor has as parameter the web api client that will be used to do networking, and the class B which is an instance of the web api.

In this example, A is a client which depends on the service B, and we have injected B inside A when we have passed it to to constructor of A.
This is the basis of the Dependency Injection pattern: when a class (Client) depends on other classes (Services), we don’t create the services inside the client, instead we provide the client with the services instances at creation time.

In the example above we have injected the external services via the constructor of the class, but there are dependency injection framework which automatically take care of injecting services as field members of a client class, without even requiring the reference passing mechanism via the client’s constructor.

2. Why should you use it?

The Dependency Injection pattern allows to:

  1. achieve separation of responsibilities,
    since we can move to dependent classes each different responsibility and then use them via injection;
  2. improve maintainability,
    because we can modify the behaviour of a dependent class without affecting how it is created or used by other classes;
  3. obtain reusable software component,
    once that the responsibility are externalised and injectable, then we can easily reuse them in other client classes;
  4. increase flexibility,
    because we can easily change the behaviour of a client class by swapping the injected dependency;
  5. reduce coupling,
    because we have separated responsibilities in different classes;
  6. help testability:
    because when dependency are injectable, then we can easily replace real classes with mocks in order to control our tests and limit their scope to units or submodules.

As everything, it comes with a price, and in this case it needs to be paid with:

  • more upfront development effort to instruct the injector framework on how to create the classes that need to be injected and how to configure injected clients;
  • possible explosion of types when there are a lot of dependencies,
  • difficulty in tracing the code because behaviour is separated from the construction.

However, considering all the benefits that DI brings to our code, we may want to pay those costs and we may even find a proper dependency injection framework for our language which help us to reduce those costs.
In the next section I will show an example of how to use one of the most popular dependency injection framework for android: Dagger.

3. How to use it? – An example in Android.

Luckily for us android developers, good people at Square have invented one of the best dependency injection framework, named Dagger, and later on Google started to improve it by releasing Dagger 2. What makes Dagger so good, is the fact that it implements the full stack of the dependency injection with generated code. This “mimics the code that a user might have hand-written to ensure that dependency injection is a simple, traceable and performant as it can be. For more background on the design, watch this talk (slides) by +Gregory Kick.“.

Ok, enough talks and theory. Show me the coooooooooooode!!!

As example I will use an app which I have built for learning purpose, it’s named “A. Cappiello Curriculum Vitae” and its complete source code is available on GitHub.

Step 1: Configure gradle.

Add to your project level gradle file the following dependencies:

Screen Shot 2016-01-30 at 17.23.34

In the app level gradle add to the top, soon after the android plugin, the following lines:

apply plugin: ''
final DAGGER_VERSION = '2.0.2'

and in the dependencies definition add

compile "${DAGGER_VERSION}"
provided "org.glassfish:javax.annotation:${JAVAX_ANNOTATION_VERSION}"

At this point sync the project with the gradle files as shown below.

Screen Shot 2016-01-30 at 16.49.15.png

Step 2: Identify dependencies which could be injected.

In my app, I use Dagger in various situations. The simplest one to analyze for the purpose of this article (without introducing other concepts like RxJava and Retrofit, which I will probably cover in other blog posts) is about the BookEntityOrchestrator class.

This class is the access point to the book entities saved in the app. It helps to read, validate and save books without worrying about the low level details related to its validation logic or kind of storage used. This low coupling is achieved by passing as parameter of the constructor three other classes, one responsible for reading books, one for validating them, and one for storing them. So whoever want to use the BookEntityOrchestrator doesn’t have to worry about the specific implementation, but it just need to know that it can read and save book entities to the local storage.

So our dependencies for the class BookEntityOrchestrator are BookSaver, BookValidator, BookReader. Moreover, we can consider BookEntityOrchestrator also a dependency for any activity which want access to Book entities.

Screen Shot 2016-01-30 at 17.21.51.png

Step 3: Create a Module class which provide the dependencies.

Dagger uses the annotation @Module to tag those classes which can provide dependencies via methods annotated with @Provides.

So in our example we will have

Screen Shot 2016-01-30 at 17.27.22

Note that in your app you can have more classes annotated with @Module and that chained dependencies like for @Provides BookEntityOrchestrator() are automatically resolved by Dagger.

Step 4: Request dependencies.

To request the classes on which your client depends upon, use the @Inject annotation, either on the constructor level or on the field level.

Since in my app I pre-fill the local db with a set of book entities on the first app launch, I need the BookEntityOrcestrator dependency in the App class. So I have a field member

BookEntityOrchestrator mBookEntityOrchestrator;

At this point you may think that the BookEntityOrchestrator also need an @Inject on his constructor in order to inject the Saver, Reader and Validator, but this it is not necessary because when we request the BookEntityOrchestrator, Dagger is smart enough to see that the method provideBookEntityOrchestrator() need more classes. So it automatically search for @Providers methods whose return type matches the input parameters needed in provideBookEntityOrchestrator().

Step 5: Bridge the provider with the consumers.

In our example, the AppModule class, annotated with @Module, is the dependency provider, while the App class, which has a field annotated with @Inject, is the consumer.
The connection between the provider and the consumer is made through an interface annotated with @Component.

Screen Shot 2016-01-30 at 17.37.33

Inside the component annotation we indicate which module need to be used as provider.
Then, for each dependency which could be provided, we have a method with empty constructor and with return type matching the type of the dependency, like BookEntityOrchestrator bookEntityOrchestrator();

Step 6: Let Dagger do the injection magic.

Before using any dependency, we need to obtain an instance of the @Component interface.
In order to do that, first we need to let Dagger to automagically create the dependency graph, by building the project a first time. Subsequently, we have access to a new class created by Dagger at compile time, DaggerAppComponent, and we use it to instantiate our @Component interface:

Screen Shot 2016-01-30 at 17.39.55.png

After the call to the inject method, the mBookEntityOrchestrator variable is automagically instantiated and ready to be used.

If we need to use the BookEntityOrchestrator in another activity, then all we need to do is to add again the field:

BookEntityOrchestrator mBookEntityOrchestrator;

and then ask dagger to inject it (usually in the onCreate method, before using the injected instance):



Those are the fundamentals to start using Dagger in your app. There is much more that you can do with it and that I haven’t covered in this post because my goal was to show you only a basic example which could allow you to appreciate the beauty behind dependency injection.

In my sample app I have also more sophisticated usage of Dagger, where I use Retrofit for networking, Dagger to inject the restful client and RxJava to handle asynchronously the updates from the web. However, since those other libraries could be new to some of you, I have preferred to cover them in a future post, after that you have mastered Dagger.

Go ahead to play with Dagger on your own and stay tuned for the next post!


3 thoughts on “Dependency injection: why and how?

  1. Pingback: Getting started with Firebase while moving away from Parse. | Antonio Cappiello

    • Thanks Ajaxian for your nice words. RxJava is on my to do list 🙂 Keep following my blog because new interesting articles will follow in the coming weeks!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s