개요
해당 게시글은 코드랩을 번역한 게시글입니다.
@Provides annotation and Qualifiers
안드로이드 프로젝트에 유용한 다른 annotation들이 있다.
@Provides
@Inject와 @Binds 외에 대거 모듈 내부에서 어떻게 객체를 제공해야하는 지 알려줄 때 @Provides를 활용할 수 있다.
@Provides 처리된 함수의 반환 타입은 대거 그래프에 추가된다. 그리고 해당 함수의 매개변수는 대거가 제공하는 방법을 알고 있어야한다.
본 포스팅 예시에서, Storage 타입을 아래와 같이 구현하여 제공할 수 있다.
StorageModule.kt
@Module
class StorageModule {
// @Provides는 이 함수의 반환 타입을 어떻게 생성하는지 알게 한다.
// 함수의 매개변수인 context는 종속성이다.
@Provides
fun provideStorage(context: Context): Storage {
// 대거가 Storage 타입을 필요로 할 때면 해당 함수가 항상 실행된다.
return SharedPreferencesStorage(context)
}
}
대거 모듈 내붸서 @Provides를 사용하여 대거에게 아래를 제공하는 방법을 알릴 수 있다:
- 인터페이스의 구현체(@Binds가 더 적은 코드를 생성하여 효율적이기 때문에 @Binds 사용을 권장)
- 해당 프로젝트의 소유물이 아닌 클래스(e.g. Retrofit 객체)
Qualifiers
이 예제는 프로젝트의 단순성으로 인해 Dagger Qualifier를 사용할 필요가 없었다. Qualifiers는 같은 타입의 다른 객체를 대거 그래프에 추가할 때 매우 유용하다. 예를들어, 서로 다른 Storage 객체를 제공하려는 경우 Qualifier를 이용하여 구분할 수 있다.
Qualifer는 종속성을 식별하는 데 사용되는 사용자 지정 annotation이다.
예를들어, SharedPreferencesStorage이 매개변수로 파일명을 받는다고 가정하자.
SharedPreferencesStorage.kt
class SharedPreferencesStorage @Inject constructor(name: String, context: Context) : Storage {
private val sharedPreferences = context.getSharedPreferences(name, Context.MODE_PRIVATE)
...
}
StoragaModule에서 @Provide를 사용한 서로 다른 구현체를 추가한다. 그리고 Qualifire를 통해 각 구현체를 구분한다.
StorageModule.kt
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class RegistrationStorage
@Retention(AnnotationRetention.BINARY)
@Qualifier
annotation class LoginStorage
@Module
class StorageModule {
@RegistrationStorage
@Provides
fun provideRegistrationStorage(context: Context): Storage {
return SharedPreferencesStorage("registration", context)
}
@LoginStorage
@Provides
fun provideLoginStorage(context: Context): Storage {
return SharedPreferencesStorage("login", context)
}
}
이 예제에서 @Provides 메소드에 사용할 수 있는 RegistrationStorage와 LoginStorage를 정의했다. 두 종류의 Storage를 그래프에 추가하게 된다. 두 메소드 모두 Storage를 반환하고, 같은 매개변수를 가지나 이름이 다르다. 왜냐하면 @Provides 함수의 이름에는 별 다른 기능이 없기 때문이다. Qualifire를 통해 그래프에서 각 종류를 검색해야 한다.
예시: Qualifire를 종속성으로 검색하는 방법
// 메서드에서 주입하는 방식
class ClassDependingOnStorage(@RegistrationStorage private val storage: Storage) { ... }
// 필드 인젝션 방식
class ClassDependingOnStorage {
@Inject
@field:RegistrationStorage lateinit var storage: Storage
}
Qualifier로서 같은 기능을 @Named로도 수행할 수 있으나 권장하지 않는다. Qualifier가 좋은 이유는 다음과 같다:
- Proguard 또는 R8에서 제거할 수 있다
- 이름을 매칭하기 위해 공유 상수를 유지할 필요가 없다
- 문서화 된다.
'안드로이드' 카테고리의 다른 글
[Android] Dagger2 주요 개념 총 정리 (0) | 2021.05.01 |
---|---|
[Android] ContributesAndroidInjector란? (0) | 2021.05.01 |
[Android] 10. 구글 코드랩 Dagger를 이용한 리팩토링 - Multiple Activities with the same scope (0) | 2021.04.28 |
[Android] 9. 구글 코드랩 Dagger를 이용한 리팩토링 - Login Flow (0) | 2021.04.28 |
[Android] 8. 구글 코드랩 Dagger를 이용한 리팩토링 - Scoping Subcomponents (0) | 2021.04.27 |