Use Dagger with kotlin

Dagger is the tool that enable to dependency injection in Java. It works to create testable and modulable application. introducing it in Kotlin is not difficult.

Environment

  • AndroidStudio 2.3
  • Kotlin 1.3

Configure the project

You need to install kotlin-kapt annotation processor.

build.gradle

apply plugin: 'kotlin-kapt'

Add the dependency of the Dagger.

build.gradle

dependencies {
  compile 'com.google.dagger:dagger:2.5'
  kapt 'com.google.dagger:dagger-compiler:2.5'
}

Module and Component

Module is the things that injects to the object. @Module means providing objects that can be injected. Here’s how to create the Module. ApplicationModule declared the function provideAPIClient. @Provides means provides objects for dependency injection and @Singleton means provides objects is reuse entire scope of module. The return value of It provides instance of APIClient declared as Interface. The Concrete type of this instance is YourAPIClient that implement APIClient. It inject to property annotated @Inject like @Inject lateinit var apiClient: APIClient.

ApplicationModule.kt

@Module
class ApplicationModule(application: Application) {

    @Singleton
    @Provides
    fun provideAPIClient(apiClient: YourAPIClient): APIClient = apiClient

}

ActivityModule.kt

@Module
class ActivityModule() {
}

Component declare dependency graph to specify which module will be injected to the object. ApplicationModule injected to YourApplication instance using inject function in the example. ActivityComponent declared as subcomponent which means can fulfill dependency object declared its and parent component. The parent component is ApplicationComponent and enable create subcomponent using fun activityComponent(module: ActivityModule): ActivityComponent. By satisfying these relationships, Injected class from ActivityModule is available to use @Inject lateinit var apiClient declared in parent component.

ApplicationComponent.kt

@Singleton
@Component(modules = arrayOf(ApplicationModule::class))
interface ApplicationComponent {
    fun inject(YourApplication: YourApplication)
    fun activityComponent(module: ActivityModule): ActivityComponent
}

ActivityComponent.kt

@Subcomponent(modules = arrayOf(ActivityModule::class))
interface ActivityComponent {
    fun inject(activity: MainActivity)
 }

Inject dependency

Create component to inject Application module. component.inject(this) means inject to required value to annotated property. The class having instance of ApplicationComponent is the top of the component graph. ActivityComponent is created in MainActivity and call inject(this) to fulfill dependency of @Inject lateinit var apiClient: APIClient. After that, We use apiClient property injected YourAPIClient.

YourApplication.kt

class YourApplication : Application() {

  lateinit var component: ApplicationComponent

  override fun onCreate() {
      super.onCreate()
      component = DaggerApplicationComponent
      .builder()
      .applicationModule(ApplicationModule(this))
      .build()
      component.inject(this)
  }

}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    @Inject lateinit var apiClient: APIClient

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val component = (application as YourApplication)
          .component
          .activityComponent(ActivityModule(this))
        component.inject(this)
      }

    private fun request() {
        apiClient.request()
    }

}
  • このエントリーをはてなブックマークに追加