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()
}
}