Demystifying the new Dagger Android Injection API 2.10+

James Shvarts
ProAndroidDev
Published in
5 min readJul 11, 2017

--

Habitat 67 features interlocking forms, connected walkways and landscaped terraces. http://www.flickr.com/photos/kindadopey/35175371126

Recent Dagger version 2.10 introduced major API changes to how dependencies are injected in an Android application. In this article I will go over a simple Android app utilizing the new API to perform injections within various scopes, including application scope, activity scope and fragment scope. If you need a primer on dependency injection, Dagger, or an in-depth comparisons between “the old” and “the new” ways, check out the Recommended Reading section below.

Visit GitHub to get the source code for this article (available in Java and Kotlin).

Why this article?

I have seen a fair amount of confusion about using the new Dagger API and the usage examples published out there vary widely. So I set out to create a sample project of my own in an attempt to present the new dagger.android API as easy to understand as possible.

For the sake of simplicity, the sample code here uses pure Activities and Fragments and does not follow any of the design patterns such as MVP or MVVM. But not for long — see the Next Steps section at the bottom of the post.

The old way

In the past, an activity could inject its dependencies by doing something like this:

The code above makes it apparent that the activity knows quite a bit about how it’s initialized with the dependencies. This violates the core principle of dependency injection known as Inversion of Control: The client delegates the responsibility of providing its dependencies to external code (the injector). The client code does not need to know about the injecting code.

Dagger 2.10+ and its dagger.android aim to address the issue above in addition to simplifying dependency injection in Android in general.

What we will cover

  1. Set up Gradle dependencies.
  2. Set up application scope dependencies and inject them into an Activity.
  3. Set up and inject dependencies for a given Activity.
  4. Set up and inject dependencies for a given Fragment.

If you follow all of the steps in this article, your project’s directory structure will look similar to this one:

Set up Gradle dependencies

Make the following changes to your app/build.gradle.

Set up application scope dependencies

First, let’s add a simple dependency, CommonHelloService, that can be injected into any class within the app.

Create a custom Application class for our application and update AndroidManifest.xml to use it. This is how we bind our application instance to our Dagger graph.

Create AppModule class where providers for all application scope components, including CommonHelloService, will be defined. Note that the latter is defined as a singleton because it makes sense for the application to have only one instance of it. Also note that I could have used constructor injection here but for the sake of consistency, I defined dependencies to be injected in each scope using classes annotated with @Module.

Create BuildersModule class which will define bindings for our sub-components so that Dagger can inject them. Note that @ContributesAndroidInjector annotation (introduced in 2.11) frees us from having to create separate components annotated with @Subcomponent .

Create the following AppComponent interface that ties them all together. It is implemented as an interface that Dagger will use to generate the code necessary to perform the dependency injection.

Create LobbyActivity which injects our CommonHelloService.

Note that the Activity injection is done in onCreate(Bundle savedInstanceState) via AndroidInjection.inject(this) before the call to super

And here is the layout file with a single TextView used to display the result of the service call:

Now when you run the app, the TextView will display “Hello from CommonHelloService”.

Set up Activity scope dependencies

Let’s create a simple dependency, LobbyHelloService, that only LobbyActivity has access to.

Provide LobbyHelloService to be injected into LobbyActivity via LobbyActivityModule:

Update BuildersModule created above to reference the LobbyActivityModule:

And finally @Inject and use the LobbyHelloService into LobbyActivity

Update lobby_activity.xml to include TextView with id lobby_hello

Now when you run the app, the TextView with id common_hello will display “Hello from CommonHelloService” while the TextView with id lobby_hello will display “Hello from LobbyHelloService”.

Set up Fragment scope dependencies

Create LobbyFragmentHelloService to be injected into our fragment below only.

Next create the LobbyFragment that will @Inject the LobbyFragmentHelloService created above.

Note that the Fragment injection is done in onAttach(Context context) via AndroidSupportInjection.inject(this) before the call to super

Now we need to update the LobbyActivity to support injecting fragments by implementing HasSupportFragmentInjector. Note, if our activity did not contain any fragments or the fragments did not need to inject anything, the activity would not need to implement HasSupportFragmentInjector.

Create LobbyFragmentModule which will provide an instance of LobbyFragmentHelloService and other dependencies for LobbyFragment:

Update BuildersModule to include the binding for injecting LobbyFragment:

Create layout file lobby_fragment.xml for our LobbyFragment:

Now let’s include the new fragment layout into our lobby_activity.xml. Note the fragment is defined statically for simplicity.

Now when you run the app, the TextView with id common_hello will display “Hello from CommonHelloService”, the TextView with id lobby_hello will display “Hello from LobbyHelloService” and, finally, the TextView with id lobby_fragment_hello will display “Hello from LobbyFragmentHelloService”.

The above code illustrates how we can inject various resources into different scopes using the new dagger.android module while ensuring that our injection clients have no knowledge about the mechanics of the injections being performed.

Next steps

I will be writing 2 more articles on applying the new Dagger setup to projects implementing MVP and MVVM design patterns commonly used in Android. Stay tuned. In the meantime, any questions or feedback (or pull requests!) are welcome.

Recommended Reading

  1. The source code for this article is available on GitHub in Java and Kotlin.
  2. Dagger 2 release notes history can be found here.
  3. Android and Dagger 2.10 AndroidInjector by Nimrod Dayan. Great overview of the Dagger 2 API differences before and after v2.10.
  4. New Android Injector with Dagger 2 — part 1 and part 2 by Mert Şimşek.

Visit my Android blog to read about Jetpack Compose and other Android topics

--

--