Dependency Injection with Dagger 1

Note: This blog post will be more geared towards Dagger within the context of Android development. I think the terms that software developers use to describe certain concepts makes simple things seem way more difficult than it is.

Dependency injection is one of them. When I first heard of the term a few years ago, my brain went, “Hmm, that sounds like a concept that will take me years to fully understand”. But nope, all it really means is you pass in instances of other objects/classes in the initialization block of a class.

In Java land, it might look something like this.

In Ruby land, probably something like this

Yes, I realize these are probably not the most extensive examples, but I hope that the readers will get the point. All dependency injection really is involves passing in instances of other objects into the target class that the target class may need to do stuff.

Enter Dagger

If you do Android development at all, you’ve probably heard of a library called Dagger. Dagger is a dependency injection framework that helps you manage dependencies in your Java applications. At the time of this writing, there are two versions of Dagger: Dagger 1 and Dagger 2. Dagger 1 was written by the fine folks are Square and Dagger 2 was written in collaboration between Square and Google, and is currently maintained by Google.

Dagger 1 vs Dagger 2 are kind of like Angular 1 vs Angular 2 (in a way…). Both Dagger 1 and Dagger 2 are dependency injection frameworks that aim to solve the problem of managing dependencies throughout your codebase. Both are independent of the Android framework and can be used in any Java application.

Dependency injection looks relatively simple, in the above code sample with the Knife class being injected into the Kitchen class. So if it looks simple, why do we need a dependency injection framework?

In real life application codebases, specifically in Android codebases in my case (since my experience working with Java is limited to Android), I found myself passing injecting dependencies in almost all of my utility classes that I’ve written to help encapsulate certain functionality. For example, one thing that I generally do in my Android applications that’s backed by an API is store user tokens in SharedPreferences. I generally end up writing a class called TokenUtil that takes in a Context as a dependency since you need a Context in order to be able to utilize SharedPreferences. So something like this.

And in my Activity classes, I always end up having to initialize my TokenUtil with the Context. For example:

This seems relatively innocent and simple, but then again, this is a simple example. I’ve seen classes that take a large amount of dependencies in order to function. And in large codebases, it becomes complicated to manage these dependencies just to utilize different classes throughout the codebase. Dagger helps to manage this chaos.

So why write a post about Dagger 1 instead of Dagger 2?

To be honest, I don’t know. I was chatting with PluralSight about authoring a course on Dagger, and they suggested that we start with Dagger 1. The reasoning was that there are still probably large amounts of codebases on Dagger 1 that have not upgraded to Dagger 2, so that there are probably many professional Android developers who still have to work with the older version of Dagger.

With that said however, if you’re starting a greenfield project, it makes no sense to go with Dagger 1 as it is no longer maintained. Just go with Dagger 2. If you’re in a situation where you still have to work with Dagger 1 however, read on.

How to use Dagger 1 within Android

As mentioned above at the beginning, this blog post will be more geared towards Dagger 1 within the context of Android development. Dagger is said to have a high learning curve. I found this to be…. not really the case. Yes, if you want to learn every little parts of Dagger, perhaps. But to start using it to reap the benefits of using a dependency injection framework, you can get started within about an hour or so. I’ll go over how to set Dagger 1 within the context of an Android application.

1. Add Dagger to your app’s build.gradle file

At the time of this writing, I believe that version 1.2.5 is the latest for Dagger 1. And since Dagger 1 is no longer maintained, it will likely be the last version released for Dagger 1.

2. Create an Application class that extends from Application

Create an Application class that extends from Application class, and set it as the app’s Application in AndroidManifest. So if your app’s name is PocketLifts (name of a side project I’m working on), you might name the class like this.

And in your AndroidManifest, set the PocketLiftsApplication as the app’s main Application class.

3. Create your Dagger modules to define your dependencies

This is where I’ll have to pause a bit and explain something called the Object Graph. Remember how the TokenUtil class required a Context class? In this case, TokenUtil has a dependency on the Context class. What if you have an object that has multiple dependencies? And what if some of those dependencies have other dependencies? You can imagine that you could draw a graph of some sort with different dependencies linking to each other via a line. Dagger draws and manages this graph for you. But in order for Dagger to be able to draw and manage this graph, you need to tell Dagger about the dependencies you want Dagger to manage in your application. We define these dependencies in Dagger modules. Let’s first write a module that will define the godfather of all dependencies in Android development, the Context class. We’ll create a class called AndroidModule where we’ll define all classes/dependencies that comes from the Android SDK.

The @ForApplication annotation is a custom annotation that ensures that the context provided by Dagger can be distinguished from the main application’s context. To define the @ForApplication annotation, create an interface that looks like this.

In the AndroidModule, the @Provides annotation marks that the provideApplicationContext method will make sure that Dagger will “provide” a Context when needed and the @Singleton annotation ensures that the Context will be a singleton.

Next, let’s create a module called PocketLiftsModule where we’ll define our custom dependencies specific to our application. In this PocketLiftsModule, we’ll have it provide the TokenUtil class mentioned above that takes in a Context as a dependency.

In here, the @Module annotation takes in a few parameters. The complete = false annotation signifies that the module is allowed to have missing dependencies. This complete variable is set to true as default, but here we’re setting it as false so that our code compiles. The more important parameter that we pass in is the injects parameter where we define the classes in the codebase where we’ll be injecting the dependencies that are defined in the module. In our case, I want to be using Dagger to inject and utilize TokenUtil in the LoginActivity class and the MainActivity class. The provideTokenUtil method takes in a Context as a parameter and it returns a new TokenUtil that’s initialized with the context.

4. Inject your modules in the Object Graph in PocketLiftsApplication

With our Dagger modules defined, let’s go back to our PocketLiftsApplication to inject our modules into the object graph so that Dagger knows what dependencies we have in our application.

Here, we set the Dagger modules that we have just created and create the ObjectGraph by setting the modules as dependencies. Then we create a new method called inject on our Application class that calls the inject method on Dagger’s object graph.

5. Create a BaseActivity class that initializes Dagger

We’ll have to create a BaseActivity class that extends from AppCompatActivity, and then initialize Dagger by overriding the onCreate class. Then we’ll have MainActivity and LoginActivity extend themselves from BaseActivity so that Dagger can be used to inject dependencies in those two classes.

6. Inject the TokenUtil dependency in LoginActivity (or MainActivity)

Dagger is all set up and ready to be used. All you have to do to initialize TokenUtil using Dagger is define the instance of a class using the @Inject annotation.

And… that’s pretty much it for setting up and using Dagger as a dependency injection framework.

So what is this object graph thing?

Remember how I mentioned Dagger’s object graph a few times throughout this blog post and how we set it up in our PocketLiftsApplication class? The way Dagger manages dependencies is by building a “graph” of dependencies in the methods marked with the @Provides annotation.

For example, our provideTokenUtil method takes in a Context as a dependency. Dagger sees that the TokenUtil requires a Context as a dependency, so it looks through the different modules that you set for the object graph to find a context. In our case, it’ll see that there are no Context in the PocketLiftsModule class, thus it’ll look in the AndroidModule class to find the Context class. It’ll then take that Context to inject and initialize the TokenUtil class and then provide a fully initialized TokenUtil class where it’s initialized it via the @Inject annotation.

Conclusion

This is just a quick overview of how to set up and use Dagger. There are definitely more configurations that you can make to use Dagger, but this guide should get you quickly set up and running.

About the Author Chris Jeon

Software developer currently focusing on Android development.