Step #3: Defining Our Module

Now we need to teach Koin how to make our ToDoRepository available via dependency inversion.

Back in ToDoApp, add this property:

  private val koinModule = module {
    single { ToDoRepository() }
  }

Here, module() is an extension function supplied by Koin, and it will need to be imported:

import org.koin.dsl.module

module() is part of a Koin domain-specific language (DSL) that describes the roster of objects to be available via dependency inversion. An app can have one or several Koin modules — for our purposes, one will be enough.

In that module, single() defines an object that will be available as a Koin-managed singleton. In our case, it is an instance of our ToDoRepository. The nice thing about Koin — and about dependency inversion frameworks in general — is that a singleton like this can be replaced where needed, such as for testing.

Simply having a Koin module is insufficient — we need to tell Koin about it. To that end, add this onCreate() function to ToDoApp:

  override fun onCreate() {
    super.onCreate()

    startKoin {
      androidLogger()
      modules(koinModule)
    }
  }

startKoin() and androidLogger() are other extension functions that will need to be imported:

import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin

As the name suggests, startKoin() starts the Koin dependency inversion engine. Like module(), startKoin() has a DSL for configuring Koin. Here, we use two configuration options, each handled via a function call:

When we start our app and Android forks a process for us, the framework will create a ToDoApp instance for our process and call onCreate(). That allows us to set up Koin before any of the rest of our code might need it.


Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.