오늘의 주제는 바로
Hilt를 사용하여 Retorfit을 사용할 때
baseUrl이 다른 두 종류의 Retrofit Builder를 사용하기
입니다.
지난 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을 뜻하죠)
여기까지 저의 긴 글을 읽어주셔서 감사합니다.
제가 습관적으로 코딩을 하는 그날까지 습관적으로 코딩을 하기 위해 글 작성을 꾸준하게 해보겠습니다.
'Android > DI' 카테고리의 다른 글
[Android] Clean Architecture + Multi Module + DI (2) | 2024.03.13 |
---|---|
[Kotlin] Koin은 DI가 아니다?! (0) | 2023.01.14 |
Android Hilt 적용하기2 (@Binds, @Provides, @ApplicationContext) (0) | 2022.12.21 |
Android Hilt 적용하기1 - (Koin vs Hilt) (2) | 2022.12.10 |
[Kotlin] Android Koin을 활용하여 DI 적용 (경량화 DI Koin) (0) | 2022.11.25 |
최근댓글