뒤늦게 코로나에 걸려 죽다 살아났습니다... 😷😷- COVID-19

 

오늘의 주제는 바로

Hilt를 사용하여 Retorfit을 사용할 때

baseUrl이 다른 두 종류의 Retrofit Builder를 사용하기

입니다.

 

 

Android Hilt 적용하기2 (@Binds, @Provides, @ApplicationContext)

Photo by Anis Rahman on Unsplash 프로젝트에 Hilt를 적용하다 막히셨나요? 🤷‍♂️🤷‍♂️ Hilt에 사용되는 @Binds, @Provides 적용에 도움되는 내용을 준비했습니다. (도움이 되었으면... 좋겠네요..❗️)

salmonpack.tistory.com

지난 Hilt 게시물에 작성한 내용과 같이 

@Qualifier 어노테이션을 사용하여 Hilt 주입 구분이 가능합니다.

 

개념을 알고 있지만 막상 직접 사용하려고 하면 머릿속이 새하얗게 변하는 이유는 뭘까요...

 

Hilt @Qualifier를 Retrofit 사용을 통하여 조금 더 알아보겠습니다.

 

@Qualifier란 무엇인가? 🤔🤔

Android Developer 사이트에서는

Provide multiple bindings for the same type이라고 정의하고 있습니다.

종속 항목과 동일한 유형의 다양한 구현을 제공해야 하는 경우 @Qualifier를 사용을 제공합니다.

 

(역시나 이해가 되지 않습니다.  😵‍💫😵‍💫

저는 직접 몸으로 경험해야 이해가 빠른 것 같네요.)

 

 

 


⚫️ BaseUrl이 다른 각각의 Retrofit 세팅

 

여기 Retorfit Module이 있습니다.

/**
 * Weather baseUrl Retrofit
 *
 * @return 설정이 반영된 Retrofit
 */
@Provides
@Singleton
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit =
    Retrofit.Builder()
        .baseUrl(C.WeatherApi.BASE_URL)
        .client(okHttpClient)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())  // Rx를 사용할 수 있도록 아답터 적용
        .addConverterFactory(ScalarsConverterFactory.create())      // ScalarConverter 적용
        .addConverterFactory(GsonConverterFactory.create())         // GsonConverter 적용
        .build()

/**
 * Air baseUrl Retrofit
 *
 * @return 설정이 반영된 Retrofit
 */
@Provides
@Singleton
fun provideAirRetrofit(okHttpClient: OkHttpClient): Retrofit =
    Retrofit.Builder()
        .baseUrl(C.AirApi.BASE_URL)
        .client(okHttpClient)
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())  // Rx를 사용할 수 있도록 아답터 적용
        .addConverterFactory(ScalarsConverterFactory.create())      // ScalarConverter 적용
        .addConverterFactory(GsonConverterFactory.create())         // GsonConverter 적용
        .build()

 

이와 같이 Retrofit을 통하여 API 통신을 만드는 경우

서로 다른 API를 사용하여 baseUrl이 다른 경우

Retrofit Builder를 각각 만들어야 하는 경우가 발생합니다.  🚨🚨

 

@Provides
@Singleton
fun weatherApi(weatherRetrofit: Retrofit): WeatherApi = weatherRetrofit.create(WeatherApi::class.java)

@Provides
@Singleton
fun airApi(airRetrofit: Retrofit): AirApi = airRetrofit.create(AirApi::class.java)

 

이와 같이 작성하게 된 이유는

weatherApi는 baseUrl이 Weather인 Retrofit Builder를 결합하여 사용되길 원하고

airApi는 baseUrl이 Air인 Retrofit Builder를 결합하여 사용하길 원합니다.

 

BUT ❗️❗️

weatherApi, airApi 두 개의 파라미터의 자료형은 모두 Retrofit입니다.

fun weatherApi(weatherRetrofit: Retrofit)  /  fun airApi(airRetrofit: Retrofit)

 

AndroidStudio 입장으로 생각해 봅시다.  🤖🤖🤖

 

Hilt를 사용하여 주입을 시도하게 됩니다.

Retrofit을 주입하려는데 두 가지 선택권이 보이네요.

하지만 두 가지의 Retrofit Buillder에는 구분할 이름도 우선순위도 없습니다.

고민에 빠지다 결국 주입을 포기하고 에러코드를 보여주며 파업을 시도하죠. 🫥🫥

 

여기서 필요한 부분이 바로

@Qualifier입니다.

동일한 여러 가지 주입 대상들에 이름표를 붙여주는 거죠!

 

 

 


⚫️  @Qualifier annotation class 정의

 

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class WeatherRetrofit

@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AirRetrofit

 

이와 같이 자신이 원하는 이름의 annotation class를 생성합니다.

생성한 annotation class들이 특정 이름표가 되는 거죠!  🏷️

 


⚫️  생성한 @Qualifier annotation 사용

 

/**
 * Weather baseUrl Retrofit
 *
 * @return 설정이 반영된 Retrofit
 */
@Provides
@Singleton
@WeatherRetrofit
fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit =
    Retrofit.Builder()
        .baseUrl(C.WeatherApi.BASE_URL)
        ...

/**
 * Air baseUrl Retrofit
 *
 * @return 설정이 반영된 Retrofit
 */
@Provides
@Singleton
@AirRetrofit
fun provideAirRetrofit(okHttpClient: OkHttpClient): Retrofit =
    Retrofit.Builder()
        .baseUrl(C.AirApi.BASE_URL)
        ...

 

주입 대상인 Retrofit Builder 생성 함수에 

위에서 만들어둔 이름표를 장착합니다.  🏷️

@WeatherRetrofit, @AirRetrofit

 

이제 baseUrl이 다른 두 Retrofit Builder에 각각 이름표가 붙었습니다.

 

@Provides
@Singleton
fun weatherApi(@NetworkModule.WeatherRetrofit weatherRetrofit: Retrofit): WeatherApi = weatherRetrofit.create(WeatherApi::class.java)

@Provides
@Singleton
fun airApi(@NetworkModule.AirRetrofit airRetrofit: Retrofit): AirApi = airRetrofit.create(AirApi::class.java)

 

이제 주입이 필요한 부분에서 붙여둔 이름표를 통해 구분하여 호출합니다.

(@WeahterRetrofit이 아니고 @NetworkModule.WeatherRetrofit인 이유는 주입대상과 주입 호출 부분이 각각 다른 class 이기 때문입니다. 즉 Network클래스의 WeatherRetrofit 이름이 붙은 Retrofit을 뜻하죠)

 

 


여기까지 저의 긴 글을 읽어주셔서 감사합니다.

제가 습관적으로 코딩을 하는 그날까지 습관적으로 코딩을 하기 위해 글 작성을 꾸준하게 해보겠습니다.

 

 

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기