Hilt Android — Step by Step : Part2
On first story, we started with very basic implementation of Hilt, check here.
In this article, we will move forward one step: provide interface and how to inject them. Let’s create an interface with a basic implementation.
Providing Interfaces:
interface LoggerCallback {
fun log()
}//Implementationclass LoggerImpl1 @Inject constructor() : LoggerCallback {
override fun log() {
Log.d("abc", "LoggerImpl1")
}
}
- There is a problem, how can we provide an interface? Here we will use
@Binds
that provided specifically for interfaces.
@Provides
fun provideLoggerImpl1(): LoggerCallback ??
- Lets add
@Binds
in our module:
@InstallIn(ActivityComponent::class)
@Module
abstract class LoggerModule {
@Provides
fun provideLogger3(@ActivityContext context: Context): Logger3 = Logger3(context)
@Binds
abstract fun provideLoggerImpl1(): LoggerCallback
}
error: A @Module may not contain both non-static and abstract binding methods
- We cannot use
@Binds
and@Provides
inside same module. Create another one for@Binds
. Both module and bind method should be abstract.
@InstallIn(ActivityComponent::class)
@Module
abstract class LoggerBindsModule {
@Binds
abstract fun bindLoggerImpl1(loggerImpl1: LoggerImpl1): LoggerCallback
}
- Inject in Activity and done!
@Inject
lateinit var loggerCallback: LoggerCallback
Different Implementation for Interfaces:
- Now, we will create second implementation for LoggerCallback and pass activity as parameter. Then
@Binds
inside our binding module.
class LoggerImpl2 @Inject constructor(private val activity: FragmentActivity) : LoggerCallback {
override fun log() {
Log.d("abc", "LoggerImpl2 : ${activity.localClassName}")
}
}//LoggerBindsModule@Binds
abstract fun bindLoggerImpl2(locationChecker: LoggerImpl2): LoggerCallback
- Run and try:
error: [Dagger/DuplicateBindings] com.example.vacation.hilt.LoggerCallback is bound multiple times:
public abstract static class ApplicationC implements VacationApplication_GeneratedInjector,
^
@org.jetbrains.annotations.NotNull @Provides com.example.vacation.hilt.LoggerCallback com.example.vacation.hilt.LoggerModule.provideLoggerImpl1()
@org.jetbrains.annotations.NotNull @Provides com.example.vacation.hilt.LoggerCallback com.example.vacation.hilt.LoggerModule.provideLoggerImpl2()
- Ups, we provide same instance two times and they need to be identified. Here we will use Qualifiers:
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class First
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class Second
- Now we need use them for our binds
@Binds
@First
abstract fun bindLoggerImpl1(loggerImpl1: LoggerImpl1): LoggerCallback
@Binds
@Second
abstract fun bindLoggerImpl2(locationChecker: LoggerImpl2): LoggerCallback
- Run..
error: [Dagger/MissingBinding] com.example.vacation.hilt.LoggerCallback cannot be provided without an @Provides-annotated method.
- We forgot to tell which logger we want inside activity:
@Inject
@First
lateinit var loggerCallback: LoggerCallback
- Done.
Conclusion:
- We learned how to provide interfaces with
@Binds
annotation and how to differentiate them with@Qualifier
. - We will continue with different lifecycle scopes on next article.