[DI] Dagger2 - Multibinding

ErroredPasta·2022년 6월 19일
0

Dependency Injection

목록 보기
5/6

Dagger2가 제공하는 기능중에 Multibinding이 있습니다. Multibinding은 같은 type의 여러 dependency를 Map이나 Set을 이용하여 하나의 object로 제공할 수 있도록 해줍니다.

Multibinding을 이용한 ViewModel factory

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가 없습니다.

Reference

[1] "Multibindings," Dagger, last modified n.d., accessed Jun 20, 2022, https://dagger.dev/dev-guide/multibindings.

profile
Hola, Mundo

0개의 댓글