Dagger2를 알아보자 – 기본편
Dagger2를 알아보자 – Scope
Dagger2를 알아보자 – Injection의 종류
Dagger2를 알아보자 – Qualifier
Dagger2를 알아보자 – Binding
Dagger2를 알아보자 – Multibinding (You’re here)
Dagger2를 알아보자 – SubComponent
Dagger2를 알아보자 – Android
Dagger2를 알아보자 – Testing(준비중)
Dagger2를 알아보자 – Dynamic Feature에 적용하기
Dagger를 사용하면 Multibinding(다중 바인딩)을 사용하여 여러 모듈에 객체가 바인딩되어 있어도 여러 객체를 하나의 컬렉션에 바인딩 할 수 있습니다. Dagger는 Collection을 조합하여 애플리케이션 코드가 독립적인 바인딩에 직접 의존하지 않고 의존성주입을 할 수 있도록 도와줍니다.
Set Multibindings
여러 인스턴스를 하나의 Set으로 관리하는 멀티바인딩을 구현하기 위해서는 @IntoSet 애노테이션을 모듈내에서 사용할 수 있습니다.
메소드의 반환형이 곧 Set의 제네릭이 되며. 반환되는 객체는 오브젝트 그래프 Set<T>로 들어가게 됩니다.
@Module public class NameModule{ @Provides @IntoSet String provideCharles(){ return "Charles"; } @Provides @IntoSet String provideRuna(){ return "Runa"; } }
@ElementsIntoSet 애노테이션을 이용하여 여러 인스턴스를 한번에 Set에 넣을 수 있습니다.
@Module public class NameModule{ @Provides @ElementsIntoSet Set<String> provideNames(){ return new HashSet<String>(Arrays.asList("Charles","Runa")); } }
제대로 주입이 되는지 확인해봅니다.
class Bar { @Inject Bar(Set<String> strings) { assert strings.contains("Charles"); assert strings.contains("Runa"); } }
컴포넌트도 Set<String>을 제공할 수 있는지 확인해봅니다.
@Component(modules = {NameModule.class}) interface MyComponent { Set<String> strings(); } @Test void testMyComponent() { MyComponent myComponent = DaggerMyComponent.create(); assertThat(myComponent.strings()).containsExactly("Charles", "Runa"); }
다른 바인딩과 마찬가지로, 멀티바인딩된 Set<String>은 Provider<Set<String>> 또는 Lazy <Set<String>>에 의존성을 주입 할 수도 있습니다. 그러나 Set<Provider<Foo>>로는 의존성 주입이 불가능합니다.
Map Multibindings
Map을 이용하여 멀티바인딩을 구현할 수도 있습니다. Set Multibinding과 방법은 비슷하며, @IntoMap 애노테이션과 @MapKey 애노테이션을 이용하면 됩니다.
컴포넌트내에 인스턴스들을 Map으로 다중 바인딩하기 위해서 Module에서는 @IntoMap을 사용합니다. Map에는 Value를 관리할 Key가 필요한데, 기정의된 Key 애노테이션으로 @StringKey, @IntLong, @LongKey, @ClassKey 등이 있습니다.
다음과 같이 Module에서 컴포넌트에 멀티바인딩 객체를 제공할 수 있습니다.
@Module class MyModule { @Provides @IntoMap @StringKey("foo") static Long provideFooValue() { return 100L; } @Provides @IntoMap @ClassKey(Thing.class) static String provideThingValue() { return "value for Thing"; } }
컴포넌트를 통해 Map이 제대로 제공 되는지 확인합니다.
@Component(modules = MyModule.class) interface MyComponent { Map<String, Long> longsByString(); Map<Class<?>, String> stringsByClass(); } @Test void testMyComponent() { MyComponent myComponent = DaggerMyComponent.create(); assertThat(myComponent.longsByString().get("foo")).isEqualTo(100L); assertThat(myComponent.stringsByClass().get(Thing.class)) .isEqualTo("value for Thing"); }
@Multibinds
컴포넌트 내에서 이미 제공된 Set이나 Map 이 있다면 모듈의 abstract 메소드에 @Multibinds 애노테이션을 추가해서 멀티바인딩을 구현할 수 있습니다. 최소한 하나이상 @IntoSet, @ElementsIntoSet 또는 @IntoMap을 갖는 Set 이나 Map을 위해서는 이 애노테이션을 추가할 필요는 없지만, 만약 Map 또는 Set이 비어있을수 있다면 사용하면 됩니다.
@Module abstract class MyModule { @Multibinds abstract Set<Foo> aSet(); @Multibinds @MyQualifier abstract Set<Foo> aQualifiedSet(); @Multibinds abstract Map<String, Foo> aMap(); @Multibinds @MyQualifier abstract Map<String, Foo> aQualifiedMap(); }
0개의 댓글