본문 바로가기

안드로이드

[Android] 11. 구글 코드랩 Dagger를 이용한 리팩토링 - @Provides & Qualifiers

개요

해당 게시글은 코드랩을 번역한 게시글입니다.

 

@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에서 제거할 수 있다
  • 이름을 매칭하기 위해 공유 상수를 유지할 필요가 없다
  • 문서화 된다.