Dependency Injection in Android with Dagger 2 and Kotlin
In this Android with Kotlin tutorial, you’ll learn about dependency injection and how to make use of the Dagger 2 Java/Android framework for this purpose. By Dario Coletto.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Dependency Injection in Android with Dagger 2 and Kotlin
30 mins
- Introduction
- What is Dependency Injection?
- Practical example of Dependency Injection
- The Dependency Inversion Principle
- How can Dagger 2 help with DI
- Getting Started
- MVP
- Dependencies in DroidWiki
- Configure the Project With Dagger 2
- Dagger 2 public APIs
- Module
- @Provides and @Singleton
- Component
- Your first (dependency) injection
- Update HomepageActivity
- The General Pattern
- Injecting the Network Graph
- NetworkModule
- Simplifying API builder
- WikiModule
- Update PresenterModule
- Update WikiApi
- Where to Go From Here?
Update Note: This Dagger 2 tutorial is now up to date with the latest version of Android Studio, version 3.0.1, and uses Kotlin for app development. Update by Dario Coletto. Original tutorial by Joe Howard.
Update Note: This Dagger 2 tutorial is now up to date with the latest version of Android Studio, version 3.0.1, and uses Kotlin for app development. Update by Dario Coletto. Original tutorial by Joe Howard.
It turns out that Dependency Injection is nowhere near as complex as its name implies. And it is a key tool for building software systems that are maintainable and testable. In the end, relying on dependency injection will simplify your code quite a bit and also allow for a clearer path to writing testable code.
In this tutorial, you’ll update an existing app named DroidWiki to use DI. The DroidWiki app is a simple wikipedia client for android, based on Dagger 2 and OkHttp 3. The Wikipedia API is based on MediaWiki, and you can find the documentation here. These API are public and there is no need to get API keys or other stuff. But you should definitely check out MediaWiki Etiquette.
Here’s a quick peek at the search result screen in DroidWiki:
Introduction
Before we begin, if you don’t know what Dependency Injection is, here’s some great news: you’re probably already using it without knowing it!
What is Dependency Injection?
First, what is a dependency? Any non-trivial software program is going to contain components that pass information and send message calls back and forth between one another.
For example, when using an Object Oriented Programming language (such as Java/Kotlin on Android), objects will call methods on other objects that they have references to. A dependency is when one of the objects depends on the concrete implementation of another object.
Practical example of Dependency Injection
Consider a practical example in Kotlin code. You can identify a dependency in your code whenever you instantiate an object within another. In such a case, you are responsible for creating and configuring the object that is being created. For example, consider the following class Parent
:
class Parent {
private val child = Child()
}
A Parent
instance creates its child
field when it’s instantiated. The Parent
instance is dependent on the concrete implementation of Child
and on configuring the child
field to use it.
This presents a coupling or dependency of the Parent
class on the Child
class. If the setup of a Child
object is complex, all that complexity will be reflected within the Parent
class as well. You will need to edit Parent
to configure a Child
object.
If the Child
class itself depends on a class C
, which in turn depends on class D
, then all that complexity will propagate throughout the code base and hence result in a tight coupling between the components of the application.
Dependency Injection is the term used to describe the technique of loosening the coupling just described. In the simple example above, only one tiny change is needed:
class Parent(private val child: Child)
Voilà — that’s dependency injection at its core!
Rather than creating the child
object inside the Parent
class, the child
object is passed into or injected into Parent
‘s constructor. The responsibility for configuring child
is elsewhere, and the Parent
class is a consumer of the Child
class.
The Dependency Inversion Principle
Dependency injection is often discussed in conjunction with one of the five SOLID principles of Object-Oriented Design: the Dependency Inversion principle. For a great introduction to the SOLID principles, particularly on Android, check out this post from Realm on Dependency Inversion.
The gist of the Dependency Inversion principle is that it is important to depend on abstractions rather than concrete implementations.
In the simple example above, this means changing Child
to a Kotlin interface
rather than a Kotlin class
. With this change, many different types of concrete Child
type objects that adhere to the Child
interface can be passed into the Parent
constructor. This presents several key benefits:
- Allows for the
Parent
class to be tested with various kinds ofChild
objects. - Mock
Child
objects can be used as needed in certain test scenarios. - Testing of
Parent
is independent of the implementation ofChild
.
How can Dagger 2 help with DI
Dagger 2 is the result of a collaboration between the team behind Guice (developed by Google) and Dagger (the predecessor of Dagger 2, created by Square).
They fixed a lot of problems from their previous work, and Dagger 2 is the faster framework for DI (since it works at compile time rather than at runtime with reflection).
Note: Dagger 2 is written in Java, but it works with Kotlin without any modification. However, the code generated by the annotation processor will be Java code (that is 100% interoperable with Kotlin).
Note: Dagger 2 is written in Java, but it works with Kotlin without any modification. However, the code generated by the annotation processor will be Java code (that is 100% interoperable with Kotlin).
The name “Dagger” is inspired in part by the nature of dependencies in software development. The web of dependencies that occur between objects such as Parent
, Child
, OtherClass
, etc., create a structure called a Directed Acyclic Graph. Dagger 2 is used to simplify the creation of such graphs in your Java and Android projects.
Enough theory! Time to start writing some code.
Getting Started
Download the starter project here.
Open the starter app in Android Studio 3.0.1 or greater and if it prompts you to update your gradle version, go ahead and do so. Run the starter app in either an emulator or on a device, and you should see a screen like the following:
The app consists of three screens. The first one is just a splashscreen.
In the second one you’ll see an HTML version of the Wikipedia homepage, obtained through the WikiMedia API. The Toolbar
at the top of the page contains a magnifier that, when tapped, will lead you to the third screen.
From there, you can type something to search on Wikipedia and press the search button to run a query. Results will be displayed as a list of CardView
s inside a RecyclerView
.
Examine the app project structure and existing classes. You’ll see that the app uses the Model-View-Presenter (MVP) pattern to structure the code. Besides Dagger 2, the app uses common Android libraries such as:
- OkHttp 3
- RecyclerView
- Kotlin synthetic properties
The subpackages in the main package are application
, model
, network
, ui
and utils
. If you explore the ui
package, you’ll see subpackages for the three screens. Except for the splashscreen, each other package has classes for the view and presenter classes for the screen.
By examining the app build.gradle file, you’ll also see that the app applies the plugin kotlin-android-extensions. It is used to implement view binding and kotlin-kapt for annotation processing.