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?
WikiModule
Next, create a new file in the dagger
package called WikiModule, and add provide methods for the API:
@Module
class WikiModule {
@Provides
@Singleton
fun provideHomepage(api: WikiApi) = Homepage(api)
@Provides
@Singleton
fun provideWiki(api: WikiApi) = Wiki(api)
}
In the NetworkModule you’ve added the provides methods for an OkHttpClient
object, an HttpUrl.Builder
object, and a WikiApi
object. Then in the WikiModule you’ve added the methods for a Homepage
and Wiki
objects, requesting dependencies from the previous methods.
This allows Dagger to construct a dependency graph, so that, for example, when an object asks for a Wiki
object to be injected, Dagger will first provide a WikiApi
and then OkHttpClient
and HttpUrl.Builder objects starting from provideWiki(api: WikiApi)
.
Dagger will then continue walking up the graph to find a baseUrl
for provideRequestBuilder(@Named(NAME_BASE_URL) baseUrl: String)
.
By using the @Singleton
annotations, only one instance of the WikiApi
and OkHttpClient
objects will be created and shared between both activities in the app.
Add your NetworkModule
and WikiModule
to AppComponent
by updating the @Component
annotation to the following:
@Component(modules = [
AppModule::class,
PresenterModule::class,
NetworkModule::class,
WikiModule::class])
Update PresenterModule
Next, update the PresenterModule
provide methods so that the Context
is passed as a constructor argument:
@Provides
@Singleton
fun provideHomepagePresenter(homepage: Homepage): HomepagePresenter = HomepagePresenterImpl(homepage)
@Provides
@Singleton
fun provideEntryPresenter(wiki: Wiki): EntryPresenter = EntryPresenterImpl(wiki)
And of course update the HomepagePresenterImpl
and EntryPresenterImpl
constructors:
class HomepagePresenterImpl @Inject constructor(private val homepage: Homepage) : HomepagePresenter {
...
}
class EntryPresenterImpl @Inject constructor(private val wiki: Wiki) : EntryPresenter {
...
}
Homepage/Wiki
constructors require a WikiApi
parameter, but we don’t need to provide it anymore as Dagger will inject it since it’s present in its graph. At this point you can remove the initialization:
private val client: OkHttpClient = OkHttpClient()
private val api: WikiApi = WikiApi(client)
private val homepage: Homepage = Homepage(api)
private val client: OkHttpClient = OkHttpClient()
private val api: WikiApi = WikiApi(client)
private val wiki: Wiki = Wiki(api)
You’ve injected the WikiApi
dependency into the presenters. This allowed you to remove the duplicated creation of the OkHttpClient
and WikiApi
objects.
Update WikiApi
As a last step, the WikiApi
class needs a constructor with an injected parameter, so you must update it:
class WikiApi @Inject constructor(private val client: OkHttpClient, private val requestBuilder: HttpUrl.Builder?) {
...
}
Now you don’t need to create an HttpUrl.Builder
each time anymore, so you can update the methods getHomepage()/search(query: String)
:
val urlBuilder = requestBuilder
?.addQueryParameter(...)
...
Now everything should be ready to go. Build and run the app, and bask in the glory of decoupled, injected code!
Where to Go From Here?
You can download the final project here.
A lot of developers asks themselves if all the changes you’ve applied to the DroidWiki app are useful or not. Especially since everything was already working before implementing dependency injection. The utility of dependency injection and a framework like Dagger 2 become most evident in real-world production apps, where the dependency graph can get very complex.
Dagger 2 and dependency injection become especially useful when implementing proper testing into your app, allowing mock implementations of back-end APIs and data repositories to be used in testing.
There’s much more to learn about in Dagger 2 and its usage, including:
- Scopes
- Subcomponents
- Testing with Mockito
There are many great resources out there on the interwebs to dive into these topics and one I must suggest is a talk by Jake Wharton at DevOxx, where you can get some more information about the history of DI on Android, some theory and some nice examples. As you do, happy injecting!
If you have any questions or comments, please join the discussion below!