Dependency Injection on Android with Dagger 2 (and Kotlin) — Part 2

Rachit M
3 min readNov 9, 2017

--

In the first part of the series, we talked about the dagger annotations and how they are useful in our projects.

In the second part we will look at how we can use Dagger 2 to provide dependencies in our mobile apps.

Add following lines to app build.gradle file

  1. The plugin kotlin-kapt (Kotlin Annotation Processor) is required for processing the kotlin annotations.
  2. The first dependency is from dagger required for annotations and other internal functionalities.
  3. The second dependency is our dagger compiler, which is required to process our dagger based annotations and generate the code.
  4. The third dependency is for Dagger android annotations.
  5. The fourth dependency is our dagger android annotation processor.
  6. The fifth dependency is optional, and it is required when we are working with Support Fragments .

For Android, the way we provide or create the object graph remain similar. What we improve on is how we inject the requested dependencies.

Injecting Dependencies

Android dependencies in activities and other framework classes are provided mostly using subcomponents.

Now, as we saw with our pure Kotlin examples in Part 1 we may easily create our component class and request a computer instance in our activities in following steps.

Let’s create an application class and instantiate our component inside it.

Application class with instantiated Computer component

Now we can use this computerComponentin our Activity and inject the dependencies as —

But there is a small issue here, A class should never know how it is being injected, But here our Activity manages the injection, which is not so bad, but not so good either.

And so there is a better approach to this —

Android Annotations

@ContributesAndroidInjector

  • This is the easiest way of injecting dependency in our Activity.
  • It is good to have custom scope for our provider function annotated with this @ContributesAndroidInjector for performance benefits discussed earlier.

Injecting Activities

Let’s take another example of injecting an activity ex.HomeActivity with HomeViewModel .

Given we have,HomeViewModel with a constructor with @Inject annotation to request the additional dependencies required to create it’s instance.

HomeViewModel with injectable constructor

We declare the activity binding using the annotation @ContributesAndroidInjector inside our ActivityBindings module.
Notice the provider is annotated with @ActivityScope custom scope.

ActivityBindings module

Next we declare our application class as

Application class

Our application class needs to implement the HasActivityInjector interface and provide a DispatchingAndroidInjector<Activity> for injecting dependencies inside our Activity.

The DispatchingAndroidInjector is again injected magically using Dagger.

We request dependencies in our Activity as

HomeActivity injected with HomeViewModel
  • The activity has to call AndroidInjection.inject(this) before the call to super so that dependencies are initialised before fragment attachments.
  • In the above code block our HomeActivity requests HomeViewModel to be injected. AndroidInjection.inject(this) requests the injectable dependencies from the Application class, which in turn using DispatchingAndroidInjector binds our dependencies to our activity.

Injecting Fragments

In a similar way we can also inject fragments with our dependencies in following steps.

Our activity hosting the fragment has to implement the HasFragmentInjector and provide an instance of DispatchingAndroidInjector<Fragment>

HomeActivity with Fragment injection

In our fragment, we request the dependency in the onAttach function.

HomeFragment requesting a dependency
Declaring activity subcomponents to provide dependencies

If you have a complex set of dependencies, the other way to provide dependencies is using subcomponents for our activities/fragments. I won’t go in much detail of that. Although you may read more about it here.

Sample Project

Issues faced

Dagger code was not being generated
- I was using annotationProcessor in place of `kapt`
- One of my projects was failing due to a missing import and the IDE wasn’t showing an error.
- I had a cyclic dependency.

NPE exception while using Android Injector
The android annotation processor was missing

Tips

  1. You shouldn’t instantiate objects in your classes rather pass them as dependencies.
  2. If the IDE isn’t working for you, Try using the command-line.
  3. Objects which request dependencies; can be easily tested using mocking. It is good to limit our constructor arguments to mockable types.

There is a lot more in Dagger 2 ex. Multibindings, Lazy injections, Provider injections etc. which we will leave for reader exploration :)

Follow the gist for the reference sources.

That’s all folks.

--

--