Using Dagger in Android – Straight to the Point

Dagger 2 is great, but it can be intimidating! It’s also difficult to find current information. This post is intended to help fix that by using a raw—“just show me what to change!—format. Here’s how I set up Dagger in a recent project. This example is in Java (as was required for my Udacity capstone project).

Initial Setup

First, add Dagger to your app’s build.gradle as shown below.

Second, create an Application class, if one doesn’t already exist, and add it to your AndroidManifest.xml. It should extend DaggerApplication and implement the abstract method applicationInjector(). Ignore the Cannot resolve symbol error; DaggerAppComponent will be generated later.

Then, create a package to contain your top-level Dagger code, such as di (for dependency injection). Inside di, add a new interface called AppComponent. It should be annotated with both @Singleton and @Component. The latter should specify a module list that includes AndroidInjectionModule. It should also include an abstract Factory class annotated with @Component.Factory that implements AndroidInjector.Factory with your Application class as the generic type argument.

Rebuild your project and expect a cannot find symbol error in your Application class. Open it to add the missing import.

Custom Scopes

Next, create the ScopeActivity and ScopeFragment annotation types in your di package. Much like how @Singleton tells Dagger to keep instances around for the life of our Application, these scopes are for the life of our Activities and Fragments.

Activities

Add an abstract inner class in AppComponent. Annotate it with @Module and add it to the @Component module list. By adding an abstract method that returns our MainActivity and annotating with ContributesAndroidInjector, we’ll cause Dagger to generate the necessary classes to inject into our Activity. The method name doesn’t matter, but stick to a convention. Also, edit your Activity so it extends DaggerAppCompatActivity. Before onCreate() is called, injected values will be assigned.

Injection

Now we’re ready! We’ll do our first silly injection example using a String. Our inner class will include a @Provides annotated method that returns a String value. Again, the name of the method doesn’t matter. In case we later have multiple String values to inject, we include a @Named annotation to allow identifying the one we want. Edit your Activity to inject the value.

As your project grows, you’ll want ActivityBindingModule to become a top-level class alongside other modules that contribute to the object graph. Keeping them together makes it easier when you’re just getting started.

Fragments

To inject into Fragments, I like to include a module class in the same package as the Fragment (as in the Google I/O 2018 App). For now, you can put it inside AppComponent. Add it to the module list of the @ContributesAndroidInjector annotation of its parent Activity. Edit the Fragment to extend DaggerFragment and add the injected String. Before onAttach() is called, injected values will be assigned.

ViewModels

Injecting into ViewModels requires a couple new classes. I recommend just pasting them into the di package.

ViewModelFactory (Rename GithubViewModelFactory to ViewModelFactory)
ViewModelKey

Add another abstract method to a new module class and add it to the modules list for contributeMainActivity().

Now we need to contribute our ViewModel into Dagger’s injectable multibound map so the factory can find it. This can be pasted just below contributeMainFragment().

Finally, we change our Activity to use our factory to obtain the ViewModel. Fragments work the same way.

Repositories

We’re almost done. Let’s see how we would inject a Repository into our ViewModel.

Add @Singleton to the repository and @Inject to the constructor. We’ll also inject our test String here as an example.

IntentService and RemoteViewsService

For IntentService, just extend DaggerIntentService, and, for RemoteViewsService, modify onCreate() as shown below. Don’t forget to add your @ContributesAndroidInjector abstract method.

The End!

Please let me know if you found this useful or if you’d like more information. Thanks!