이전에 Dagger2를 이용하여 dependency injection을 하는 방법에 대해 알아보았습니다. Dagger2의 경우 Module과 Component를 정의하고 Component간 구조를 사용자가 일일이 정의를 해주고 마지막으로 Component를 생성하여 dependency들을 주입하였습니다.
Dagger Hilt는 Dagger2를 보다 간편하게 사용하기 위해 boilerplate 코드를 줄여주어 간단하게 dependency injection을 할 수 있습니다.
해당 글에서는 Plugin을 이용한 Dagger Hilt에 대해서 다루며 Plugin을 사용하지 않은 Dagger Hilt는 아래의 GitHub 링크를 참고해주시면 됩니다.
Dagger Hilt의 미리 정의된 Component와 Scope를 제공합니다.
위와 같이 Component는 Subcomponent 혹은 부모 Component를 가지고 필요시 부모 Component에서 제공하는 dependency를 가져옵니다.
해당 Component들은 사용자가 직접 생성해서 사용하는 것이 아니라 Dagger Hilt에서 자동으로 생성하여 @Inject
로 dependency들을 주입하게 됩니다.
Module은 Dagger2와 동일하나 @InstallIn
을 이용하여 어떤 Component에 설치될지 지정해주어야 합니다.
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}).build()
private const val BASE_URL = "https://v6.exchangerate-api.com/"
@Provides
@Singleton
fun provideExchangeRateApi(
okHttpClient: OkHttpClient
): ExchangeRateApi = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(ExchangeRateApi::class.java)
}
해당 코드는 Module을 @InstallIn(SingletonComponent::class)
로 SingletonComponent에 설치하며 해당 Component에서 같은 객체를 사용할 dependency에 알맞는 Scope인 @Singleton
을 적용했습니다.
Module들을 정의하고 알맞은 Component에 설치를 했으면 어디에서 코드 생성을 시작하고 dependency를 주입할지 지정해주어야 합니다.
@HiltAndroidApp
kicks off the code generation of the Hilt components and also generates a base class for your application that uses those generated components.
@HiltAndroidApp
class ConversionApplication : Application()
Dagger Hilt를 사용할 때 Application을 상속받는 클래스에 @HiltApplication
annotation을 적용시켜서 코드 생성을 시작할 수 있도록 해주어야 합니다.
Once you have enabled members injection in your Application, you can start enabling members injection in your other Android classes using the
@AndroidEntryPoint
annotation
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
...
}
@AndroidEntryPoint
는 Activity, Fragment 등과 같은 Android의 클래스에 적용이 되며 dependency를 주입할 수 있도록 해줍니다. 적용될 수 있는 클래스는 다음과 같습니다.
이 중에서 BroadcastReceiver는 위에서 봤듯이 Component가 없습니다. 그래서 SingletonComponent에서 dependency를 주입받습니다.
그리고 dependency가 주입되도록 하려면 자신을 포함하고 있는 클래스 또한 @AndroidEntryPoint
가 적용되어 있어야 합니다. 즉, Fragment의 경우 자신을 포함하고 있는 Activity에도 @AndroidEntryPoint
가 적용이 되어 있어야 dependency가 주입가능합니다.
A Hilt View Model is a Jetpack ViewModel that is constructor injected by Hilt. To enable injection of a ViewModel by Hilt use the
@HiltViewModel
annotation
Dagger Hilt의 장점중 하나는 ViewModel을 주입하기가 쉽습니다. Dagger2를 사용할 때는 아래와 같은 과정이 필요했습니다.
@MapKey
를 이용한 annotation 정의ViewModel
type으로 bind 및 Map key 설정하지만 Dagger Hilt를 사용하면 단순히 정의한 ViewModel에 @HiltViewModel
를 적용해주면 됩니다.
@HiltViewModel
class MainViewModel @Inject constructor(
private val repository: ConversionRepository
) : ViewModel() {
...
}
이렇게 annotation을 적용했으면 @AndroidEntryPoint
가 적용된 곳에서 ViewModel의 instance를 가져와서 사용할 수 있습니다.
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private val viewModel by viewModels<MainViewModel>()
...
}
[1] "Hilt," Dagger, last modified n.d., accessed Feb 27, 2023, https://dagger.dev/hilt/.
[2] "Hilt Components," Dagger, last modified n.d., accessed Feb 27, 2023, https://dagger.dev/hilt/components.
[3] "Hilt Application," Dagger, last modified n.d., accessed Feb 27, 2023, https://dagger.dev/hilt/application.
[4] "Android Entry Points," Dagger, last modified n.d., accessed Feb 27, 2023, https://dagger.dev/hilt/android-entry-point.
[5] "View Models," Dagger, last modified n.d., accessed Feb 27, 2023, https://dagger.dev/hilt/view-model.