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.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

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!