Google의 Dagger를 기반으로 만든 의존성 주입 라이브러리입니다.
Hilt 라이브러리는 Application Class와 Application Context에 접근해서 의존성을 주입하기 때문에 Application Class가 필요합니다.
@HiltAndroidApp 이라는 Annotation을 추가해주어야 합니다.
@HiltAndroidApp
class MyApplication : Application() { ... }
@HiltAndroidApp에 의해서 SingletonComponent가 생성됩니다.
앱이 살아있는 동안 의존성을 제공하는 역할을 하는, 애플리케이션 레벨의 Component.
Android 클래스에 @AndroidEntryPoint로 주석을 지정하면 이 클래스에 종속된 Android 클래스에도 주석을 지정해야 합니다. 예를 들어 프래그먼트에 주석을 지정하면 이 프래그먼트를 사용하는 활동에도 주석을 지정해야 합니다.
그리고, Application 클래스를 생성한 뒤에는 매니페스트 파일 application 태그에 name을 설정해줘야 합니다.
Hilt는 컴포넌트들을 이용해서 필요한 의존성을 클래스에 제공합니다.
Hilt가 의존성을 주입해 줄 수 있는 클래스의 종류
컴포넌트들은 아래와 같은 계층을 가지고 있습니다.
또한 해당 컴포넌트들은 아래와 같은 함수 호출시점에 생성되고, Destroy 됩니다.
어떤 곳에 해당 의존성이 필요하다고 어노테이션이 붙어있다면, 해당하는 객체를 어떻게 생성하는지 Hilt가 알고 있어야 합니다.
Hilt에 의해 주입받을 수 있는 객체의 클래스라는 것을 알려주기 위해 @Inject 어노테이션이 필요합니다.
Field Injection과 Constructor Injection이 있습니다.
주의할 점은, Hilt에 의해 주입받은 변수 객체는 private할 수 없습니다.
Interface는 Constructor Injection에 사용할 수 없습니다.
Hilt가 interface가 implement된 타입의 객체를 어떻게 생성해야 할지 알 수 없기 때문입니다.
Module을 이용해서 Hilt에게 원하는 의존성을 생성하는 방법을 알려줄 수 있습니다.
interface나 외부 라이브러리의 객체처럼, Hilt가 어떻게 객체를 생성해야할지 모르는 경우에는 꼭 필요한 방법입니다.
Module을 사용하는 방법은 Provides, Binds 두가지가 있습니다.
Module 클래스를 생성하고 @Module 어노테이션으로 여기가 Module이 있는 곳임을 알 수 있습니다.
다음으로 @InstallIn 어노테이션을 붙여줘야 합니다.
@InstallIn(ActivityComponent::class)는 해당 모듈이 activity에서 사용 가능하다고 선언한다는 의미입니다.
같은 타입일 경우, 어떤 Type 객체를 주입할지 Hilt가 알 수 없습니다.
@Qualifier로 식별자를 Hilt에 알려주어 구분해줄 수 있습니다.
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AuthInterceptorOkHttpClient
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@AuthInterceptorOkHttpClient
@Provides
fun provideAuthInterceptorOkHttpClient(
authInterceptor: AuthInterceptor
): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(authInterceptor)
.build()
}
}
Binds방식은 외부 라이브러리에는 사용할 수 없고, interface 타입의 객체를 어떻게 만드는지 Hilt에게 알려주기 위한 용도로 사용됩니다.
abstract class를 만든다음, abstract 함수를 정의해 주면 됩니다.
어디서 객체를 생성해야 할지 모르는 Hilt에게 어떤 클래스로부터 가져온 객체라고 알려주는 것입니다.
@Module
@InstallIn(ActivityComponent::class)
abstract class AModule {
@Binds
abstract fun bindInterfaceDependency(testClassB: ClassB): AInterface
}
@ActivityScoped
class AnalyticsAdapter @Inject constructor(
private val service: AnalyticsService
) { ... }
위 코드에서 @AcitivityScoped를 사용했는데 이는 Activity 생명주기 동안 동일한 AnlysticsAdapter 인스턴스를 사용한다는 의미입니다.
앱의 모든 위치에서 동일한 인스턴스를 사용해야한다면(Singleton 패턴을 사용해야 한다면) 아래의 예제와 같이 설정해줘야 합니다.
@ApplicationContext를 사용해주면 Hilt가 알아서 생성해주므로, 바로 사용이 가능합니다.
@Module
@InstallIn(ActivityComponent::class)
class AModule {
@Provides
fun provideTest(@ApplicationContext appContext: Context): Test {
return Test(appContext)
}
}
class AnalyticsAdapter @Inject constructor(
@ActivityContext private val context: Context,
private val service: AnalyticsService
) { ... }
https://developer88.tistory.com/349
https://medium.com/androiddevelopers/scoping-in-android-and-hilt-c2e5222317c0