Dagger2가 제공하는 기능중에 Multibinding이 있습니다. Multibinding은 같은 type의 여러 dependency를 Map이나 Set을 이용하여 하나의 object로 제공할 수 있도록 해줍니다.
Dagger2를 이용할 때 multibinding을 사용해야하는 대표적인 경우로 ViewModel을 생성시 필요한 ViewModelProvider.Factory
를 상속하여 구현할 때 Map multibinding이 사용됩니다.
class MainViewModel @Inject constructor(
private val repository: ConversionRepository
) : ViewModel() {
...
}
class SecondViewModel @Inject constructor(
private val secondDependency: SecondDependency
) : ViewModel() {
...
}
우선 map multibinding을 사용하기 위해서는 @MapKey
를 이용하여 Map에 dependency를 넣을 때 지정할 key annotation class를 정의해야 합니다.
@MapKey
annotation class ViewModelKey(val key: KClass<out ViewModel>)
ViewModelProvider.Factory에서 ViewModel을 생성 시 생성할 클래스의 type을 넘겨주므로 ViewModelKey
도 클래스의 type을 받도록 하였습니다.
이제 ViewModel들을 ViewModel
type으로 bind하고 @IntoMap
을 이용하여 Map에 넣어야 합니다.
@Module
interface ViewModelModule {
// @IntoMap을 이용하여 Map에 MainViewModel을 ViewModel type으로 넣도록
// @ViewModelKey를 이용하여 Map에 넣을 때 사용할 key값을 제공
@Binds
@IntoMap
@ViewModelKey(MainViewModel::class)
fun bindMainViewModel(viewModel: MainViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(SecondViewModel::class)
fun bindSecondViewModel(viewModel: SecondViewModel): ViewModel
}
이렇게 했으면 이제 Map을 이용하여 ViewModel들을 주입할 수 있게 됩니다.
마지막으로 ViewModelProvider.Factory
를 상속받는 factory를 구현해주고 ViewModelProvider.Factory
로 bind해주면 됩니다.
class ViewModelFactory @Inject constructor(
private val providerMap: @JvmSuppressWildcards Map<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return providerMap[modelClass]!!.get() as T
}
}
@Module
interface ViewModelModule {
...
// ViewModelFactory를 ViewModelProvider.Factory로 bind하여
// ViewModel을 생성할 때 사용할 수 있도록 함
@Binds
fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
}
Set을 이용한 multibinding은 Map multibinding과 매우 유사합니다. 차이점은 Map multibinding은 Map에 넣을 때 사용할 key를 @MapKey
를 이용하여 정의하고 @IntoMap
을 할 때 정의한 Map key를 사용해야 했지만 Set에는 key가 없습니다.
[1] "Multibindings," Dagger, last modified n.d., accessed Jun 20, 2022, https://dagger.dev/dev-guide/multibindings.