Image for post
Image for post

Dagger & Android Thoughts: Dependency Injection in Android

Manuel Vivo
Mar 28, 2018 · 5 min read

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?

Image for post
Image for post

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.15 works.

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.

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.

Image for post
Image for post

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?

Image for post
Image for post
Dagger & Android Graph

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?

Image for post
Image for post
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 previously.

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 in Android.

Thanks for reading,

Manuel Vicente Vivo

Capital One Tech

The low down on our high tech from the engineering experts…

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