The Missing Link — What Dagger 2 Newbie Guides Don’t Tell You

Hugo Rheinhold’s Affe mit Schädel (by Darwin Monkey)

After spending the past year learning Android development, I’m at that newbie stage where you’ve written enough apps, hit so many challenges, that you start to understand how much there is yet to learn. There are a number of design patterns out there worth looking into, some of them already getting traction at major Silicon Valley companies as well as in open source communities.

Enter the Dagger

For example, there’s a ton of code out there that uses Dagger 2. To even be able to read that code, you need to understand Dagger 2. So I’ve been spending a lot of time on GitHub poring through sample code, and reading articles about how it works and how to set it up.

So far, the clearest resources I’ve found are

What’s missing?

All three have clear examples of using Dagger 2 to keep objects unaware of the implementation details of any other objects they depend on. My next move would be to try writing my own simple example code to increase my understanding. Looking at the examples answered most of my questions, but unfortunately also raised a few.

  • Why do so many of the Android examples provide Singletons?
  • Why do the examples extend the Application to build classes from the Components?
  • What’s the deal with calling what looks like an arbitrary generic method of the component that was constructed by the App?

Trial and error

Maybe I’m a little dense, but I find it hard to just start cranking out code without connecting the dots.

But, I already had simple app, Recipe Browser, that illustrates a few Android patterns, like ViewPager and Fragments. I decided to refactor it a bit to try out Dagger 2. In particular, it uses a food-related data model, Recipe. The main Activity’s onCreate() method populates a List of Recipes from a JSON stream that comes embedded with in the App’s Assets. The List is used to populate a RecyclerView, and is a parameter to its Adapter.

The goal was to inject the list as a member variable of the Activity. Dagger 2 would automatically instantiate or find the best instance of a class that would provide me with the ArrayList<Recipe>

Good old code

In the original code, onCreate() used a helper method to load the ArrayList:

In the revised version, the ArrayList becomes an injected member variable of the Activity class:

@Inject ArrayList<Recipe> recipes;

That way the Activity gets access to the Recipe list without any implementation details, including knowing or caring where the data comes from.

In order for this to work, a few things have to happen.

  1. A module needs to exist that can provide an ArrayList<Recipe>
  2. Dagger 2 needs to build a component that can instantiate the module
  3. The Activity needs to be hooked into the component

The missing links

This is what gave rise to my original questions. I’ll try to address them, provide the missing links.

  • Why do so many of the Android examples provide Singletons?
    It’s all about lifecycle. Does the object your Activity uses need to be tied to the Activity’s lifecycle? If it could exist outside the Activity, would that make things more efficient, not having to re-instantiate the object each time the Activity is created? If the answer is yes, then a Singleton might be the way to go.
  • Why do the examples extend the Application to build classes from the Components?
    Again, lifecycle. The Application is the an aspect of your App that always lives outside the lifecycle of all the Activities. It can always be counted on to be there at any time, in any Activity. And if you’re implementing Singletons, the Application is where you want them to be rooted.
  • What’s the deal with calling what looks like an arbitrary generic method of the component that was constructed by the App?
    This is where the Activity (or any other class whose dependencies are satisfied by Dagger 2) gets hooked into the mechanism that satisfies the dependencies. Any class that does that needs to have a method defined in the component whose signature includes an instance of the class as an argument.

Good new code

In this case he module is simple, refactored from the getRecipesFromAsset() method in the original Activity. I decided a Singleton would work well here

The Application was the best place to root the Component

The Component has a single method that is called by the RecipeListActivity to place itself into Dagger 2’s food chain:

The Application builds the component and saves it as a member variable, and defines the getter getRecipeComponent(). The static method getApp() delivers a link to the Application. An Activity could just as well use getApplication() to do the same thing, but other kinds of classes in general cannot.

Finally, the main Activity simply specifies via annotation that its recipes member variable is fulfilled by Dagger 2, and “registers” to be a part of the process by passing a reference to itself to the Dagger 2 component that was built in the application. That gets done early on — typically in onCreate() in an Activity or Fragment, or in a constructor in other general classes — before the member variable actually gets accessed.

And it still works!

So that’s it. Nothing got broken. The code was refactored, Dagger 2 got added into the mix, and from the user’s point of view the app hasn’t changed a bit!

Of course this is all naive, incomplete, oversimplified, not a precise specification of what’s really going on. But it should be enough to get you started coding. A trivial working example is your first step toward real understanding.