11. Dagger 바인딩의 종류
@Binds
- 모듈 내의 추상 메서드에 붙일 수 있음
- 추상 메서드 앞에 붙여 Binding을 위임 하는 annotation
- 반드시 하나의 매개 변수만을 가져야 함
- 매개 변수를 반환형으로 바인드할 수 있다.
@Provides
메서드 대신 좀 더 효율적으로 사용할 수 있다.
@Module
abstract class MyModuleRandom{
@Binds
abstract fun bindRandom(secureRandom: SecureRandom):Random
}
- Random 객체를 SecureRandom 객체에 바인딩
@Binds
는 객체를 생성하는 대신 Component 내에 있는 객체를 파라미터로 받아 바인딩하여 좀 더 효율적으로 동작하게 해줌- 좀 더 자세한 예제 보러가기 (jaejong님의 블로그 글)
@BindsOptionalOf
- 모듈 내의 추상 메서드에 붙일 수 있음
- 매개 변수를 가질 수 없음
- unit이 아닌 특정 타입을 반환해야함
- 예외를 던질 수 없음
- Java Optional 에 대해 구글링해보고 넘어가자
- Optional 은 메소드의 결과가 null이 될 수 있으며, 클라이언트가 이 상황을 처리해야 할 때 사용하는 것이 좋다.
import dagger.BindsOptionalOf
import dagger.Module
@Module
abstract class CommonModule {
@BindsOptionalOf
abstract fun bindOptionalOfString():String
}
import dagger.Module
import dagger.Provides
@Module
class HelloModule {
@Provides
fun providesString() = "Hello"
}
@BindsOptionalOf
메서드를 통한 의존성의 주입은 다음과 같은 Optional 타입 등으로 주입
import dagger.Lazy
import java.util.*
import javax.inject.Inject
import javax.inject.Provider
class Foo {
@Inject
lateinit var str: Optional<String> // @Nullable 바인딩은 허용하지 않음
@Inject
lateinit var str2: Optional<Provider<String>>
@Inject
lateinit var str3: Optional<Lazy<String>>
}
- 컴포넌트 내에 Foo가 바인드된 적이 있으면 Optional 상태는 present, 아니라면 absent
- 특징: 어떤 타입의 의존성이 바인드되었는지 여부와 관계없이 @Inject를 이용해 주입할 수 있다.
[Test를 위한 컴포넌트 2개]
import dagger.Component
@Component(modules = [CommonModule::class, HelloModule::class])
interface StrComponent {
fun inject(foo: Foo)
}
import dagger.Component
@Component(modules = [CommonModule::class])
interface NoStrComponent {
fun inject(foo: Foo)
}
[Test code]
@Test
fun test_Foo(){
val foo = Foo()
DaggerStrComponent.create().inject(foo)
println(foo.str.isPresent) // true
println(foo.str.get()) // Hello
DaggerNoStrComponent.create().inject(foo)
println(foo.str.isPresent) // false
println(foo.str.get()) // java.util.NoSuchElementException: No value present
}
- 처음에 생성한 컴포넌트는 string을 바인드 받았기 때문에
isPresent == true
- 두번째 생성한 컴포넌트는 바인드 되지 않아서
isPresent == false
- 바인드 되지 않은
Optional<String>
을get()
하면 예외가 발생하는 것을 알 수 있었음
@BindsInstance
- 컴포넌트 빌더의 세터 메서드 또는 컴포넌트 팩토리의 매개 변수에 붙일 수 있음
- 모듈이 아닌 외부로 부터 생성된 인스턴스를 빌더 또는 팩토리를 통해서 넘겨줌으로써 컴포넌트가 해당 인스턴스를 반인드
- 이러한 인스턴스들은 마찬가지로
@Inject
가 붙은 필드, 생성자, 메서드에 주입 가능
예제
import dagger.BindsInstance
import dagger.Component
@Component
interface BindsComponent {
fun inject(foo: Foo)
@Component.Builder
interface Builder {
@BindsInstance
fun setString(str: String): Builder
fun build(): BindsComponent
}
}
import javax.inject.Inject
class Foo {
@Inject
lateinit var str: String
}
테스트 코드
@Test
fun test_bindsInstance() {
val hello = "Hello World"
val foo = com.lilcode.hellodagger.bindsInstance.Foo()
val component = DaggerBindsComponent.builder()
.setString(hello)
.build()
component.inject(foo)
assertEquals("Hello World", foo.str)
}
- 외부로부터 생성한 String 객체를 바인드
2021.07.25 - [Android/클린 아키텍처] - [Clean Architecture] 11-범위 지정하기 (@Scope)
2021.07.24 - [Android/클린 아키텍처] - [Clean Architecture] 10-한정자 (@named)
2021.07.23 - [Android/클린 아키텍처] - [Clean Architecture] 09-Lazy 주입 & Provider 주입 (dagger)
해당 글은 '아키텍처를 알아야 앱 개발이 보인다' 를 공부하며 요약 정리한 글 입니다.
'Android > 클린 아키텍처' 카테고리의 다른 글
[Clean Architecture] 14-Dagger 서브 컴포넌트, 상속 (0) | 2021.08.03 |
---|---|
[Clean Architecture] 13-Dagger 멀티 바인딩 하기 (0) | 2021.07.27 |
[Clean Architecture] 11-범위 지정하기 (@Scope) (0) | 2021.07.25 |
[Clean Architecture] 10-한정자 (@named) (0) | 2021.07.24 |
[Clean Architecture] 09-Lazy 주입 & Provider 주입 (dagger) (0) | 2021.07.23 |