software engineering Mar 8, 2018

Dagger & Android Thoughts: Dependency Injection in Android

I’ve been researching about Dagger & Android to see if I should start using it in my projects or not. But before I get into that, here’s some context for this post.

Edit 4/2/18: This article specifically talks about the package, not about Dagger in general as a DI solution for Android.

Edit 8/8/18: After few ideas from the community, this is currently under investigation. I’ll update the post with more information soon. After all, it might be possible to have Dagger Android working with multiple Component layers.

Who is This Article For?

target audience for dagger and android

Benefits of Dagger & Android

From the Dagger documentation — Many Android framework classes are instantiated by the OS itself, like Activity and Fragment. You have to perform members injection in a lifecycle method which causes a few problems:

  • Copy-pasting code makes it hard to refactor later on.
  • It requires the type requesting injection to know about its injector.

Dagger Android Injections offers one approach to simplify Dependency Injection with Dagger in Android


This article is based on my understanding of how Dagger & Android v2.15works.

There’s an open issue on the Dagger Github to clarify this. I’m looking forward to hearing back from Google or Dagger including this functionality in future versions.

Dagger Android with multiple levels of (Sub)Components · Issue #1087 · google/dagger
I wonder if it's possible to have different levels of Components or Subcomponents using Dagger Android. The idea is…

When Should I Use It?

From my point of view, it’s a really good solution for small projects , but I don’t see it scaling well in larger applications for a few reasons.

Potential drawbacks for a large app

  • All subcomponents extend from the ApplicationComponent.
  • Because of the above point, all the components will need to declare which modules they use without being able to extract them out and modularize the graph properly. There’s only one level of abstraction.
  • Any Android class that uses DI needs to be declared in the ApplicationComponent.
  • Testing would require the whole structure to be duplicated with test instances, meaning not having that much control over the mocks.

IMO, all these points are a red flag in a large app. A large application should be structured in a more composable way with the ability of extracting common logic to reusable components.

If the above points matter for your use case, Dagger & Android is maybe not the DI tool for you.

However, there are use cases where Dagger & Android make sense.

Common Use Case

How would the Graph look with just one feature and two screens if you use Dagger & Android?

Android Injections

Dagger & Android doesn’t allow you to have common (Sub)Components making it harder to structure and reuse code.

That graph doesn’t scale. Can you image how it would be with eight features and three screens per feature?

I’d prefer having a custom solution based on Dagger with a better and less error-prone structure that allows us to reuse as much code as possible. What about something like this?

Custom solution graph

Dagger & Android Generated Code

Let’s take a look at how Dagger & Android works under the hood. To inject an Activity, the only thing you have to do is:


1. What is AndroidInjection.inject doing?

public static void inject(Activity activity) {
  checkNotNull(activity, "activity");
  Application application = activity.getApplication();
  if (!(application instanceof HasActivityInjector)) {
    throw new RuntimeException(
            "%s does not implement %s",
  AndroidInjector<Activity> activityInjector =
      ((HasActivityInjector) application).activityInjector();
  checkNotNull(activityInjector, "%s.activityInjector() returned null", application.getClass());

2. How does it know which Subcomponent Builder to use?

When you map an Activity with its Builder in a Module attached to the ApplicationComponent with some code like so:

abstract class ActivityBuilder {

    abstract fun bindMainActivity(builder:MainSubcomponent.Builder):
            AndroidInjector.Factory<out Activity>


In your generated class, it binds the Activity with the instance of the Builder you defined previous

private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
    getMapOfClassOfAndProviderOfFactoryOf() {
  return MapBuilder
      .<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
      .put(MainActivity.class, (Provider) mainSubcomponentBuilderProvider)

3. Inject the Builder to the class

When you call inject, it’s going to call the inject method on the instance of the Builder implementation defined in the second step.


To reiterate again on the point mentioned above: this article is based on my research, reading, and experimentation.

I recommend doing some of your own before deciding if Dagger & Android is suitable for your project.

Do you want to know more about Dagger? Check out this other article about Surviving Configuration Changes using Dagger

DISCLOSURE STATEMENT: These opinions are those of the author. Unless noted otherwise in this post, Capital One is not affiliated with, nor is it endorsed by, any of the companies mentioned. All trademarks and other intellectual property used or displayed are the ownership of their respective owners. This article is © 2018 Capital One.