Dagger.android — The Missing Deep Dive

Lisa Watkins
Mar 9, 2019 · 4 min read

I know what you’re thinking — not another Dagger article. There are a ton of great resources out there that explain the basics of dependency injection with Dagger. This article is not one of those. I’m going to assume that you are familiar with Dagger, and I’m also going to assume that you’ve probably used Dagger in one of your applications.

The fundamental problem with Dagger and Android applications is that without Dagger.android , any Android component that you want to inject has to know about how it is injected. We get a lot of code like this:

Yuck, this definitely violates a major principle of dependency injection: a class should never know about how it is injected.

This is why I want to specifically talk about Dagger.android and why, after working with Dagger in my projects for over a year, I feel as though I’ve finally seen the light. This is how Dagger is supposed to look and feel with your Android projects.

First things first, lets define our ApplicationComponent and ApplicationModule.

Notice that the first module included in ApplicationComponent is AndroidInjectionModule. This module provides the bindings for all Android framework base types (activities, fragments, services, and broadcast receivers).

In ActivityModule and FragmentModule, notice the annotation @ContributesAndroidInjector. This annotation is purely syntactic sugar to bind an AndroidInjector with the activity or fragment. When you look at the generated code for ActivityModule_ContributesMainActivity, you’ll see a generated map binding with the activity name as the key and a subcomponent that extends AndroidInjector .

Generated code below:

When we look at more generated code later, it will become more clear how Dagger is building AndroidInjectors to inject our activities and fragments.

Now, the real bread and butter of using Dagger.android — our application does not need to know anything about how it is injected. The work can be deferred to ApplicationInjector.

Moving on to our Application class…

As you can see, we’ve implemented HasActivityInjector and we’ve overridden activityInjector() to return an injected instance of DispatchingAndroidInjector<Activity> . When ApplicationInjector builds the application component, you can see that in the generated code we land here…

Generated code below:

We’re setting up MainActivity's subcomponent builder. When ApplicationInjector moves on to inject BaseApplication, we land here…

Generated code below:

When we inject BaseApplcation, we also inject its member variables. See getDispatchingAndroidInjectorOfActivity? This is exactly how we inject BaseApplication's dispatchingAndroidInjector with the proper map. So far we just have one entry, MainActivity and its subcomponent. Now every time we inject an activity in our application, we check for it in dispatchingAndroidInjector to complete the injection.

Now it is clear that @ContributesAndroidComponent generates a map of our activity classes to their subcomponent builders, which each in turn generate a map of all their child fragments and their subcomponent builders.

Now, lets take a look at MainActivity.

Just how our Application class impelmented HasActivityInjector , our MainActivity class implements HasSupportFragmentInjector. Same exact deal here. Our DispatchingAndroidInjector<Fragment> member variable is injected with the mapping of our fragments to their subcomponent builders.

Now, all we have to do to inject our activities and fragments is call AndroidInjection.inject(activity) and AndroidSupportInjection.inject(fragment) . Lets check out what AndroidInjection.inject(activity) is doing.

dagger.android.AndroidInjection

We first make sure that our Application class is an instance of HasActivityInjector — then we call .activityInjector(). Remember we implemented that method in BaseApplication? Here we return the DispatchingAndroidInjector<Activity> instance that has a list of AndroidInjector factories. If we can’t find the mapping, we’ll throw an exception. If all is well and we do find the mapping, we’ll call inject() and our subcomponents factory will handle all member variable injection for our Android component.

A really nifty way to handle AndroidInjection.inject is to register it in lifecycle callbacks for your application and have your injectable fragments implement an empty interface. I called my empty interface Injectable. Check out an updated version of ApplicationInjector below:

Now, any time we create a fragment, if it implements Injectable we take care of the injection.

I hope this article conveys how excited I am to be using Dagger.android in my projects, and why you should too. Hopefully this article also demystified how things are working underneath the hood, and its clear how you can use Dagger.android to inject all your Android components moving forward.

Thanks for reading, and happy coding!

Code With Lisa

Learn about mobile development with Lisa Watkins, a mobile tech lead at Lyft and Android enthusiast.

Lisa Watkins

Written by

Engineer, Activist, Cat Lady. Mobile engineering @ Lyft.

Code With Lisa

Lisa Watkins is a self-taught mobile developer. Code with Lisa aims to share knowledge in the mobile engineering space.

Lisa Watkins

Written by

Engineer, Activist, Cat Lady. Mobile engineering @ Lyft.

Code With Lisa

Lisa Watkins is a self-taught mobile developer. Code with Lisa aims to share knowledge in the mobile engineering space.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store