[DI] Dagger Hilt

ErroredPasta·2023년 2월 27일
0

Dependency Injection

목록 보기
6/6

이전에 Dagger2를 이용하여 dependency injection을 하는 방법에 대해 알아보았습니다. Dagger2의 경우 Module과 Component를 정의하고 Component간 구조를 사용자가 일일이 정의를 해주고 마지막으로 Component를 생성하여 dependency들을 주입하였습니다.

Dagger Hilt는 Dagger2를 보다 간편하게 사용하기 위해 boilerplate 코드를 줄여주어 간단하게 dependency injection을 할 수 있습니다.
해당 글에서는 Plugin을 이용한 Dagger Hilt에 대해서 다루며 Plugin을 사용하지 않은 Dagger Hilt는 아래의 GitHub 링크를 참고해주시면 됩니다.

Plugin 없는 Dagger Hilt

Component 구조와 Scope

Dagger Hilt의 미리 정의된 Component와 Scope를 제공합니다.

위와 같이 Component는 Subcomponent 혹은 부모 Component를 가지고 필요시 부모 Component에서 제공하는 dependency를 가져옵니다.

해당 Component들은 사용자가 직접 생성해서 사용하는 것이 아니라 Dagger Hilt에서 자동으로 생성하여 @Inject로 dependency들을 주입하게 됩니다.

Module

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을 적용했습니다.

Hilt Application과 Android Entry Point

Module들을 정의하고 알맞은 Component에 설치를 했으면 어디에서 코드 생성을 시작하고 dependency를 주입할지 지정해주어야 합니다.

Hilt Application

@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을 적용시켜서 코드 생성을 시작할 수 있도록 해주어야 합니다.

Android Entry Point

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를 주입할 수 있도록 해줍니다. 적용될 수 있는 클래스는 다음과 같습니다.

  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

이 중에서 BroadcastReceiver는 위에서 봤듯이 Component가 없습니다. 그래서 SingletonComponent에서 dependency를 주입받습니다.

그리고 dependency가 주입되도록 하려면 자신을 포함하고 있는 클래스 또한 @AndroidEntryPoint가 적용되어 있어야 합니다. 즉, Fragment의 경우 자신을 포함하고 있는 Activity에도 @AndroidEntryPoint가 적용이 되어 있어야 dependency가 주입가능합니다.

ViewModel

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를 사용할 때는 아래와 같은 과정이 필요했습니다.

  1. Map multibinding에 사용할 @MapKey를 이용한 annotation 정의
  2. Module에서 사용자가 정의한 ViewModel을 ViewModel type으로 bind 및 Map key 설정
  3. ViewModel을 생성할 때 사용할 factory 클래스 정의
  4. Map multibinding을 이용하여 ViewModel을 담고 있는 Map을 factory에 주입
  5. ViewModel을 생성할 factory를 주입받아서 ViewModel 생성

하지만 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>()
    
    ...
}

Reference

[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.

profile
Hola, Mundo

0개의 댓글