Set Multibinding¶
Table of Contents¶
- Overview
- Contributing to a Set
- Combining with @AutoBinds
- Choosing a component
- Selecting specific binding targets
- Generated code
Overview¶
Use @AutoBindsIntoSet to contribute a class or Kotlin object into a Dagger
multibinding Set of each direct supertype (implemented interfaces and extended
parent classes). This lets you collect multiple implementations automatically
without maintaining a manual module.
Contributing to a Set¶
Annotate each implementation with @AutoBindsIntoSet:
@AutoBindsIntoSet
class LoggingInterceptor @Inject constructor() : Interceptor {
override fun intercept(chain: Chain): Response { /* ... */ }
}
@AutoBindsIntoSet
class AuthInterceptor @Inject constructor() : Interceptor {
override fun intercept(chain: Chain): Response { /* ... */ }
}
Now you can inject Set<Interceptor> anywhere and Hilt will collect all
contributions automatically:
class ApiClient @Inject constructor(
private val interceptors: Set<@JvmSuppressWildcards Interceptor>,
) {
// interceptors contains LoggingInterceptor and AuthInterceptor
}
Warning
The annotation @JvmSuppressWildcards is required when injecting a map.
This is a current limitation of Dagger 2 library, since it generates Java
source code under the hood.
Combining with @AutoBinds¶
@AutoBindsIntoSet can be combined with @AutoBinds on the same class to
produce both a direct binding and a set contribution:
@AutoBinds // provides Interceptor directly
@AutoBindsIntoSet // also contributes to Set<Interceptor>
class DefaultInterceptor @Inject constructor() : Interceptor { /* ... */ }
This generates two separate modules with different names to avoid conflicts.
Choosing a Component¶
@AutoBindsIntoSet supports the same installIn parameter as @AutoBinds.
It defaults to HiltComponent.Unspecified with auto-detection from scope
annotations:
@ActivityScoped
@AutoBindsIntoSet // installed in ActivityComponent (auto-detected)
class ActivityInterceptor @Inject constructor() : Interceptor { /* ... */ }
@AutoBindsIntoSet(installIn = HiltComponent.ViewModel)
class ViewModelInterceptor @Inject constructor() : Interceptor { /* ... */ }
See Scopes and Components for the full reference.
Selecting Specific Binding Targets¶
By default, @AutoBindsIntoSet contributes the class to a Set of every
direct supertype. Use bindTo to restrict which supertypes are included or to
target a grandparent:
interface BaseHandler
open class AbstractHandler : BaseHandler
// Contributes to Set<BaseHandler> only, skipping AbstractHandler
@AutoBindsIntoSet(bindTo = [BaseHandler::class])
class MyHandler @Inject constructor() : AbstractHandler()
bindTo accepts any transitive supertype. An error is emitted at compile time
if a listed type is not a supertype of the annotated class.
Generated Code¶
For each annotated class, the processor generates an interface Hilt module
with @Binds @IntoSet functions:
@Module
@InstallIn(SingletonComponent::class)
internal interface LoggingInterceptor__IntoSetModule {
@Binds @IntoSet
fun bindToInterceptor(impl: LoggingInterceptor): Interceptor
}
For each annotated object, the processor generates an object Hilt module
with @Provides @IntoSet functions:
@Module
@InstallIn(SingletonComponent::class)
internal object NoOpInterceptor__IntoSetModule {
@Provides @IntoSet
fun bindToInterceptor(): Interceptor = NoOpInterceptor
}
The same requirements as basic usage apply.