Hilt는 프로젝트에서 종속 항목 수동 삽입을 실행하는 상용구를 줄이는 Android용 종속 항목 삽입 라이브러리입니다. 종속 항목 수동 삽입을 실행하려면 모든 클래스와 종속 항목을 수동으로 구성하고 컨테이너를 사용하여 종속 항목을 재사용 및 관리해야 합니다.
Hilt는 프로젝트의 모든 Android 클래스에 컨테이너를 제공하고 수명 주기를 자동으로 관리함으로써 애플리케이션에서 DI를 사용하는 표준 방법을 제공합니다. Hilt는 Dagger가 제공하는 컴파일 시간 정확성, 런타임 성능, 확장성 및 Android 스튜디오 지원의 이점을 누리기 위해 인기 있는 DI 라이브러리인 Dagger를 기반으로 빌드되었습니다. 자세한 내용은 Hilt 및 Dagger를 참조하세요.
이 가이드에서는 Hilt의 기본 개념 및 생성된 컨테이너에 관해 설명합니다. 또한 데모를 통해 기존 앱을 부트스트랩하여 Hilt를 사용하는 방법을 보여줍니다.
종속 항목 추가
먼저 hilt-android-gradle-plugin
플러그인을 프로젝트의 루트 build.gradle
파일에 추가합니다.
Groovy
plugins { ... id 'com.google.dagger.hilt.android' version '2.51.1' apply false }
Kotlin
plugins { ... id("com.google.dagger.hilt.android") version "2.51.1" apply false }
그런 다음, Gradle 플러그인을 적용하고 app/build.gradle
파일에 다음 종속 항목을 추가합니다.
Groovy
... plugins { id 'kotlin-kapt' id 'com.google.dagger.hilt.android' } android { ... } dependencies { implementation "com.google.dagger:hilt-android:2.51.1" kapt "com.google.dagger:hilt-compiler:2.51.1" } // Allow references to generated code kapt { correctErrorTypes true }
Kotlin
plugins { id("kotlin-kapt") id("com.google.dagger.hilt.android") } android { ... } dependencies { implementation("com.google.dagger:hilt-android:2.51.1") kapt("com.google.dagger:hilt-android-compiler:2.51.1") } // Allow references to generated code kapt { correctErrorTypes = true }
Hilt는 자바 8 기능을 사용합니다. 프로젝트에서 자바 8을 사용 설정하려면 app/build.gradle
파일에 다음을 추가합니다.
Groovy
android { ... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } }
Kotlin
android { ... compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } }
Hilt 애플리케이션 클래스
Hilt를 사용하는 모든 앱은 @HiltAndroidApp
으로 주석이 지정된 Application
클래스를 포함해야 합니다.
@HiltAndroidApp
은 애플리케이션 수준 종속 항목 컨테이너 역할을 하는 애플리케이션의 기본 클래스를 비롯하여 Hilt의 코드 생성을 트리거합니다.
Kotlin
@HiltAndroidApp class ExampleApplication : Application() { ... }
자바
@HiltAndroidApp public class ExampleApplication extends Application { ... }
생성된 이 Hilt 구성요소는 Application
객체의 수명 주기에 연결되며 이와 관련한 종속 항목을 제공합니다. 또한 이는 앱의 상위 구성요소이므로 다른 구성요소는 이 상위 구성요소에서 제공하는 종속 항목에 액세스할 수 있습니다.
Android 클래스에 종속 항목 삽입
Application
클래스에 Hilt를 설정하고 애플리케이션 수준 구성요소를 사용할 수 있게 되면 Hilt는 @AndroidEntryPoint
주석이 있는 다른 Android 클래스에 종속 항목을 제공할 수 있습니다.
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { ... }
자바
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { ... }
Hilt는 현재 다음 Android 클래스를 지원합니다.
Application
(@HiltAndroidApp
을 사용하여)ViewModel
(@HiltViewModel
을 사용하여)Activity
Fragment
View
Service
BroadcastReceiver
Android 클래스에 @AndroidEntryPoint
로 주석을 지정하면 이 클래스에 종속된 Android 클래스에도 주석을 지정해야 합니다. 예를 들어 프래그먼트에 주석을 지정하면 이 프래그먼트를 사용하는 활동에도 주석을 지정해야 합니다.
@AndroidEntryPoint
는 프로젝트의 각 Android 클래스에 관한 개별 Hilt 구성요소를 생성합니다. 이러한 구성요소는 구성요소 계층 구조에 설명된 대로 해당하는 각 상위 클래스에서 종속 항목을 받을 수 있습니다.
구성요소에서 종속 항목을 가져오려면 다음과 같이 @Inject
주석을 사용하여 필드 삽입을 실행합니다.
Kotlin
@AndroidEntryPoint class ExampleActivity : AppCompatActivity() { @Inject lateinit var analytics: AnalyticsAdapter ... }
자바
@AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @Inject AnalyticsAdapter analytics; ... }
Hilt가 삽입하는 클래스에는 삽입도 사용하는 다른 기본 클래스가 있을 수 있습니다.
이러한 클래스는 추상적인 경우 @AndroidEntryPoint
주석이 필요하지 않습니다.
Android 클래스가 삽입되는 수명 주기 콜백에 관한 자세한 내용은 구성요소 전체 기간을 참고하세요.
Hilt 결합 정의
필드 삽입을 실행하려면 Hilt가 해당 구성요소에서 필요한 종속 항목의 인스턴스를 제공하는 방법을 알아야 합니다. 결합에는 특정 유형의 인스턴스를 종속 항목으로 제공하는 데 필요한 정보가 포함됩니다.
Hilt에 결합 정보를 제공하는 한 가지 방법은 생성자 삽입입니다. 다음과 같이 클래스의 생성자에서 @Inject
주석을 사용하여 클래스의 인스턴스를 제공하는 방법을 Hilt에 알려줍니다.
Kotlin
class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
자바
public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
주석이 지정된 클래스 생성자의 매개변수는 그 클래스의 종속 항목입니다. 이 예에서 AnalyticsAdapter
에는 AnalyticsService
가 종속 항목으로 있습니다. 따라서 Hilt는 AnalyticsService
의 인스턴스를 제공하는 방법도 알아야 합니다.
Hilt 모듈
때로 유형을 생성자 삽입할 수 없는 상황도 있습니다. 이러한 상황은 여러 가지 이유로 인해 발생할 수 있습니다. 예를 들어 인터페이스를 생성자 삽입할 수 없습니다. 또한 외부 라이브러리의 클래스와 같이 소유하지 않은 유형도 생성자 삽입할 수 없습니다. 이럴 때는 Hilt 모듈을 사용하여 Hilt에 결합 정보를 제공할 수 있습니다.
Hilt 모듈은 @Module
로 주석이 지정된 클래스입니다. Dagger 모듈과 마찬가지로 이 모듈은 특정 유형의 인스턴스를 제공하는 방법을 Hilt에 알려줍니다. 그러나 Dagger 모듈과는 달리, Hilt 모듈에 @InstallIn
주석을 지정하여 각 모듈을 사용하거나 설치할 Android 클래스를 Hilt에 알려야 합니다.
Hilt 모듈에 제공하는 종속 항목은 Hilt 모듈을 설치하는 Android 클래스와 연결되어 있는 모든 생성된 구성요소에서 사용할 수 있습니다.
@Binds를 사용하여 인터페이스 인스턴스 삽입
AnalyticsService
예를 생각해 보세요. AnalyticsService
가 인터페이스라면 이 인터페이스를 생성자 삽입할 수 없습니다. 대신 Hilt 모듈 내에 @Binds
로 주석이 지정된 추상 함수를 생성하여 Hilt에 결합 정보를 제공합니다.
@Binds
주석은 인터페이스의 인스턴스를 제공해야 할 때 사용할 구현을 Hilt에 알려줍니다.
주석이 지정된 함수는 Hilt에 다음 정보를 제공합니다.
- 함수 반환 유형은 함수가 어떤 인터페이스의 인스턴스를 제공하는지 Hilt에 알려줍니다.
- 함수 매개변수는 제공할 구현을 Hilt에 알려줍니다.
Kotlin
interface AnalyticsService { fun analyticsMethods() } // Constructor-injected, because Hilt needs to know how to // provide instances of AnalyticsServiceImpl, too. class AnalyticsServiceImpl @Inject constructor( ... ) : AnalyticsService { ... } @Module @InstallIn(ActivityComponent::class) abstract class AnalyticsModule { @Binds abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl ): AnalyticsService }
자바
public interface AnalyticsService { void analyticsMethods(); } // Constructor-injected, because Hilt needs to know how to // provide instances of AnalyticsServiceImpl, too. public class AnalyticsServiceImpl implements AnalyticsService { ... @Inject AnalyticsServiceImpl(...) { ... } } @Module @InstallIn(ActivityComponent.class) public abstract class AnalyticsModule { @Binds public abstract AnalyticsService bindAnalyticsService( AnalyticsServiceImpl analyticsServiceImpl ); }
Hilt가 AnalyticsModule의 종속 항목을 ExampleActivity
에 삽입하기를 원하기 때문에 Hilt 모듈 AnalyticsModule
에 @InstallIn(ActivityComponent.class)
주석을 지정합니다. 이 주석은 AnalyticsModule
의 모든 종속 항목을 앱의 모든 활동에서 사용할 수 있음을 의미합니다.
@Provides를 사용하여 인스턴스 삽입
유형을 생성자 삽입할 수 없는 것은 인터페이스만이 아닙니다.
클래스가 외부 라이브러리에서 제공되므로 클래스를 소유하지 않은 경우(Retrofit, OkHttpClient
또는 Room 데이터베이스와 같은 클래스) 또는 빌더 패턴으로 인스턴스를 생성해야 하는 경우에도 생성자 삽입이 불가능합니다.
이전 예를 생각해 보세요. AnalyticsService
클래스를 직접 소유하지 않으면 Hilt 모듈 내에 함수를 생성하고 이 함수에 @Provides
주석을 지정하여 이 유형의 인스턴스를 제공하는 방법을 Hilt에 알릴 수 있습니다.
주석이 달린 함수는 Hilt에 다음 정보를 제공합니다.
- 함수 반환 유형은 함수가 어떤 유형의 인스턴스를 제공하는지 Hilt에 알려줍니다.
- 함수 매개변수는 해당 유형의 종속 항목을 Hilt에 알려줍니다.
- 함수 본문은 해당 유형의 인스턴스를 제공하는 방법을 Hilt에 알려줍니다. Hilt는 해당 유형의 인스턴스를 제공해야 할 때마다 함수 본문을 실행합니다.
Kotlin
@Module @InstallIn(ActivityComponent::class) object AnalyticsModule { @Provides fun provideAnalyticsService( // Potential dependencies of this type ): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService::class.java) } }
Java
@Module @InstallIn(ActivityComponent.class) public class AnalyticsModule { @Provides public static AnalyticsService provideAnalyticsService( // Potential dependencies of this type ) { return new Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService.class); } }
동일한 유형에 대해 여러 결합 제공
종속 항목과 동일한 유형의 다양한 구현을 제공하는 Hilt가 필요한 경우에는 Hilt에 여러 결합을 제공해야 합니다. 한정자를 사용하여 동일한 유형에 대해 여러 결합을 정의할 수 있습니다.
한정자는 특정 유형에 대해 여러 결합이 정의되어 있을 때 그 유형의 특정 결합을 식별하는 데 사용하는 주석입니다.
다음 예를 생각해 보세요. AnalyticsService
호출을 가로채야 한다면 인터셉터와 함께 OkHttpClient
객체를 사용할 수 있습니다. 다른 서비스에서는 호출을 다른 방식으로 가로채야 할 수도 있습니다. 이 경우에는 서로 다른 두 가지 OkHttpClient
구현을 제공하는 방법을 Hilt에 알려야 합니다.
먼저 다음과 같이 @Binds
또는 @Provides
메서드에 주석을 지정하는 데 사용할 한정자를 정의합니다.
Kotlin
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class AuthInterceptorOkHttpClient @Qualifier @Retention(AnnotationRetention.BINARY) annotation class OtherInterceptorOkHttpClient
자바
@Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface AuthInterceptorOkHttpClient {} @Qualifier @Retention(RetentionPolicy.RUNTIME) private @interface OtherInterceptorOkHttpClient {}
그런 다음, Hilt는 각 한정자와 일치하는 유형의 인스턴스를 제공하는 방법을 알아야 합니다. 이 경우에는 @Provides
와 함께 Hilt 모듈을 사용할 수 있습니다.
두 메서드 모두 동일한 반환 유형을 갖지만 한정자는 다음과 같이 두 가지의 서로 다른 결합으로 메서드에 라벨을 지정합니다.
Kotlin
@Module @InstallIn(SingletonComponent::class) object NetworkModule { @AuthInterceptorOkHttpClient @Provides fun provideAuthInterceptorOkHttpClient( authInterceptor: AuthInterceptor ): OkHttpClient { return OkHttpClient.Builder() .addInterceptor(authInterceptor) .build() } @OtherInterceptorOkHttpClient @Provides fun provideOtherInterceptorOkHttpClient( otherInterceptor: OtherInterceptor ): OkHttpClient { return OkHttpClient.Builder() .addInterceptor(otherInterceptor) .build() } }
자바
@Module @InstallIn(ActivityComponent.class) public class NetworkModule { @AuthInterceptorOkHttpClient @Provides public static OkHttpClient provideAuthInterceptorOkHttpClient( AuthInterceptor authInterceptor ) { return new OkHttpClient.Builder() .addInterceptor(authInterceptor) .build(); } @OtherInterceptorOkHttpClient @Provides public static OkHttpClient provideOtherInterceptorOkHttpClient( OtherInterceptor otherInterceptor ) { return new OkHttpClient.Builder() .addInterceptor(otherInterceptor) .build(); } }
다음과 같이 필드 또는 매개변수에 해당 한정자로 주석을 지정하여 필요한 특정 유형을 삽입할 수 있습니다.
Kotlin
// As a dependency of another class. @Module @InstallIn(ActivityComponent::class) object AnalyticsModule { @Provides fun provideAnalyticsService( @AuthInterceptorOkHttpClient okHttpClient: OkHttpClient ): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .client(okHttpClient) .build() .create(AnalyticsService::class.java) } } // As a dependency of a constructor-injected class. class ExampleServiceImpl @Inject constructor( @AuthInterceptorOkHttpClient private val okHttpClient: OkHttpClient ) : ... // At field injection. @AndroidEntryPoint class ExampleActivity: AppCompatActivity() { @AuthInterceptorOkHttpClient @Inject lateinit var okHttpClient: OkHttpClient }
자바
// As a dependency of another class. @Module @InstallIn(ActivityComponent.class) public class AnalyticsModule { @Provides public static AnalyticsService provideAnalyticsService( @AuthInterceptorOkHttpClient OkHttpClient okHttpClient ) { return new Retrofit.Builder() .baseUrl("https://example.com") .client(okHttpClient) .build() .create(AnalyticsService.class); } } // As a dependency of a constructor-injected class. public class ExampleServiceImpl ... { private final OkHttpClient okHttpClient; @Inject ExampleServiceImpl(@AuthInterceptorOkHttpClient OkHttpClient okHttpClient) { this.okHttpClient = okHttpClient; } } // At field injection. @AndroidEntryPoint public class ExampleActivity extends AppCompatActivity { @AuthInterceptorOkHttpClient @Inject OkHttpClient okHttpClient; ... }
한정자를 유형에 추가한다면 그 종속 항목을 제공하는 가능한 모든 방법에 한정자를 추가하는 것이 좋습니다. 기본 또는 일반 구현을 한정자 없이 그대로 두면 오류가 발생하기 쉬우며 Hilt가 잘못된 종속 항목을 삽입할 수 있습니다.
Hilt의 사전 정의된 한정자
Hilt는 몇 가지 사전 정의된 한정자를 제공합니다. 예를 들어 애플리케이션 또는 활동의 Context
클래스가 필요할 수 있으므로 Hilt는 @ApplicationContext
및 @ActivityContext
한정자를 제공합니다.
예의 AnalyticsAdapter
클래스에 활동 컨텍스트가 필요하다고 가정해 보겠습니다. 다음 코드는 AnalyticsAdapter
에 활동 컨텍스트를 제공하는 방법을 보여줍니다.
Kotlin
class AnalyticsAdapter @Inject constructor( @ActivityContext private val context: Context, private val service: AnalyticsService ) { ... }
자바
public class AnalyticsAdapter { private final Context context; private final AnalyticsService service; @Inject AnalyticsAdapter( @ActivityContext Context context, AnalyticsService service ) { this.context = context; this.service = service; } }
Hilt에서 사용 가능한 사전 정의된 다른 결합은 구성요소 기본 결합을 참고하세요.
Android 클래스용으로 생성된 구성요소
필드 삽입을 실행할 수 있는 각 Android 클래스마다 @InstallIn
주석에 참조할 수 있는 관련 Hilt 구성요소가 있습니다.
각 Hilt 구성요소는 해당 Android 클래스에 결합을 삽입해야 합니다.
이전 예에서는 Hilt 모듈에서 ActivityComponent
를 사용하는 방법을 보여주었습니다.
Hilt는 다음 구성요소를 제공합니다.
Hilt 구성요소 | 인젝터 대상 |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
N/A |
ViewModelComponent |
ViewModel |
ActivityComponent |
Activity |
FragmentComponent |
Fragment |
ViewComponent |
View |
ViewWithFragmentComponent |
@WithFragmentBindings 주석이 지정된 View |
ServiceComponent |
Service |
구성요소 전체 기간
Hilt는 해당 Android 클래스의 수명 주기에 따라 생성된 구성요소 클래스의 인스턴스를 자동으로 만들고 제거합니다.
생성된 구성요소 | 생성 위치 | 소멸 위치 |
---|---|---|
SingletonComponent |
Application#onCreate() |
Application 소멸됨 |
ActivityRetainedComponent |
Activity#onCreate() |
Activity#onDestroy() |
ViewModelComponent |
ViewModel 생성됨 |
ViewModel 소멸됨 |
ActivityComponent |
Activity#onCreate() |
Activity#onDestroy() |
FragmentComponent |
Fragment#onAttach() |
Fragment#onDestroy() |
ViewComponent |
View#super() |
View 소멸됨 |
ViewWithFragmentComponent |
View#super() |
View 소멸됨 |
ServiceComponent |
Service#onCreate() |
Service#onDestroy() |
구성요소 범위
기본적으로 Hilt의 모든 결합은 범위가 지정되지 않습니다. 즉, 앱이 결합을 요청할 때마다 Hilt는 필요한 유형의 새 인스턴스를 생성합니다.
이 예에서 Hilt는 다른 유형의 종속 항목으로 또는 필드 삽입을 통해(ExampleActivity
에서와 같이) AnalyticsAdapter
를 제공할 때마다 AnalyticsAdapter
의 새 인스턴스를 제공합니다.
그러나 Hilt는 결합을 특정 구성요소로 범위 지정할 수도 있습니다. Hilt는 결합의 범위가 지정된 구성요소의 인스턴스마다 한 번만 범위가 지정된 결합을 생성하며, 이 결합에 관한 모든 요청은 동일한 인스턴스를 공유합니다.
아래 표에는 생성된 각 구성요소의 범위 주석이 나와 있습니다.
Android 클래스 | 생성된 구성요소 | 범위 |
---|---|---|
Application |
SingletonComponent |
@Singleton |
Activity |
ActivityRetainedComponent |
@ActivityRetainedScoped |
ViewModel |
ViewModelComponent |
@ViewModelScoped |
Activity |
ActivityComponent |
@ActivityScoped |
Fragment |
FragmentComponent |
@FragmentScoped |
View |
ViewComponent |
@ViewScoped |
@WithFragmentBindings 주석이 지정된 View |
ViewWithFragmentComponent |
@ViewScoped |
Service |
ServiceComponent |
@ServiceScoped |
이 예에서 @ActivityScoped
를 사용하여 AnalyticsAdapter
의 범위를 ActivityComponent
로 지정하면 Hilt는 해당 활동의 수명 주기 동안 동일한 AnalyticsAdapter
인스턴스를 제공합니다.
Kotlin
@ActivityScoped class AnalyticsAdapter @Inject constructor( private val service: AnalyticsService ) { ... }
자바
@ActivityScoped public class AnalyticsAdapter { private final AnalyticsService service; @Inject AnalyticsAdapter(AnalyticsService service) { this.service = service; } ... }
AnalyticsService
에 ExampleActivity
뿐만 아니라 앱의 모든 위치에서 매번 동일한 인스턴스를 사용해야 하는 내부 상태가 있다고 가정해 보겠습니다. 이럴 때에는 AnalyticsService
의 범위를 SingletonComponent
로 지정하는 것이 적절합니다. 결과적으로 구성요소는 AnalyticsService
의 인스턴스를 제공해야 할 때마다 매번 동일한 인스턴스를 제공합니다.
다음 예에서는 Hilt 모듈에서 결합의 범위를 구성요소로 지정하는 방법을 보여줍니다. 결합의 범위는 결합이 설치된 구성요소의 범위와 일치해야 하므로 이 예에서는 ActivityComponent
대신 SingletonComponent
에 AnalyticsService
를 설치해야 합니다.
Kotlin
// If AnalyticsService is an interface. @Module @InstallIn(SingletonComponent::class) abstract class AnalyticsModule { @Singleton @Binds abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl ): AnalyticsService } // If you don't own AnalyticsService. @Module @InstallIn(SingletonComponent::class) object AnalyticsModule { @Singleton @Provides fun provideAnalyticsService(): AnalyticsService { return Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService::class.java) } }
자바
// If AnalyticsService is an interface. @Module @InstallIn(SingletonComponent.class) public abstract class AnalyticsModule { @Singleton @Binds public abstract AnalyticsService bindAnalyticsService( AnalyticsServiceImpl analyticsServiceImpl ); } // If you don't own AnalyticsService. @Module @InstallIn(SingletonComponent.class) public class AnalyticsModule { @Singleton @Provides public static AnalyticsService provideAnalyticsService() { return new Retrofit.Builder() .baseUrl("https://example.com") .build() .create(AnalyticsService.class); } }
Hilt 구성요소 범위에 관한 자세한 내용은 Android 및 Hilt의 범위 지정을 참고하세요.
구성요소 계층 구조
구성요소에 모듈을 설치하면 이 구성요소의 다른 결합 또는 구성요소 계층 구조에서 그 아래에 있는 하위 구성요소의 다른 결합의 종속 항목으로 설치된 모듈의 결합에 액세스할 수 있습니다.
구성요소 기본 결합
각 Hilt 구성요소는 Hilt가 고유한 맞춤 결합에 종속 항목으로 삽입할 수 있는 기본 결합 세트와 함께 제공됩니다. 이러한 결합은 일반 활동 및 프래그먼트 유형에 해당하며 특정 서브클래스에는 해당되지 않습니다. 이는 Hilt가 모든 활동을 삽입하는 데 단일 활동 구성요소 정의를 사용하기 때문입니다. 각 활동에는 이 구성요소의 다른 인스턴스가 있습니다.
Android 구성요소 | 기본 결합 |
---|---|
SingletonComponent |
Application |
ActivityRetainedComponent |
Application |
ViewModelComponent |
SavedStateHandle |
ActivityComponent |
Application , Activity |
FragmentComponent |
Application , Activity , Fragment |
ViewComponent |
Application , Activity , View |
ViewWithFragmentComponent |
Application , Activity , Fragment , View |
ServiceComponent |
Application , Service |
애플리케이션 컨텍스트 결합은 @ApplicationContext
를 통해 사용할 수도 있습니다.
예를 들면 다음과 같습니다.
Kotlin
class AnalyticsServiceImpl @Inject constructor( @ApplicationContext context: Context ) : AnalyticsService { ... } // The Application binding is available without qualifiers. class AnalyticsServiceImpl @Inject constructor( application: Application ) : AnalyticsService { ... }
자바
public class AnalyticsServiceImpl implements AnalyticsService { private final Context context; @Inject AnalyticsAdapter(@ApplicationContext Context context) { this.context = context; } } // The Application binding is available without qualifiers. public class AnalyticsServiceImpl implements AnalyticsService { private final Application application; @Inject AnalyticsAdapter(Application application) { this.application = application; } }
활동 컨텍스트 결합은 @ActivityContext
를 통해 사용할 수도 있습니다. 예를 들면 다음과 같습니다.
Kotlin
class AnalyticsAdapter @Inject constructor( @ActivityContext context: Context ) { ... } // The Activity binding is available without qualifiers. class AnalyticsAdapter @Inject constructor( activity: FragmentActivity ) { ... }
Java
public class AnalyticsAdapter { private final Context context; @Inject AnalyticsAdapter(@ActivityContext Context context) { this.context = context; } } // The Activity binding is available without qualifiers. public class AnalyticsAdapter { private final FragmentActivity activity; @Inject AnalyticsAdapter(FragmentActivity activity) { this.activity = activity; } }
Hilt가 지원하지 않는 클래스에 종속 항목 삽입
Hilt에는 가장 일반적인 Android 클래스에 관한 지원이 함께 제공됩니다. 그러나 Hilt가 지원하지 않는 클래스에 필드 삽입을 실행해야 할 수도 있습니다.
이러한 경우 @EntryPoint
주석을 사용하여 진입점을 만들 수 있습니다. 진입점은 Hilt가 관리하는 코드와 그렇지 않은 코드 사이의 경계입니다. 즉, Hilt가 관리하는 객체의 그래프에 코드가 처음 들어가는 지점입니다. 진입점을 통해 Hilt는 Hilt가 관리하지 않는 코드를 사용하여 종속 항목 그래프 내에서 종속 항목을 제공할 수 있습니다.
예를 들어 Hilt는 콘텐츠 제공자를 직접 지원하지 않습니다. 콘텐츠 제공자가 Hilt를 사용하여 일부 종속 항목을 가져오도록 하려면 원하는 결합 유형마다 @EntryPoint
로 주석이 지정된 인터페이스를 정의하고 한정자를 포함해야 합니다. 그리고 다음과 같이 @InstallIn
을 추가하여 진입점을 설치할 구성요소를 지정합니다.
Kotlin
class ExampleContentProvider : ContentProvider() { @EntryPoint @InstallIn(SingletonComponent::class) interface ExampleContentProviderEntryPoint { fun analyticsService(): AnalyticsService } ... }
자바
public class ExampleContentProvider extends ContentProvider { @EntryPoint @InstallIn(SingletonComponent.class) interface ExampleContentProviderEntryPoint { public AnalyticsService analyticsService(); } ... }
진입점에 액세스하려면 EntryPointAccessors
의 적절한 정적 메서드를 사용하세요. 매개변수는 구성요소 인스턴스이거나 구성요소 소유자 역할을 하는 @AndroidEntryPoint
객체여야 합니다. 매개변수로 전달하는 구성요소와 EntryPointAccessors
정적 메서드가 모두 @EntryPoint
인터페이스의 @InstallIn
주석에 있는 Android 클래스와 일치하는지 확인합니다.
Kotlin
class ExampleContentProvider: ContentProvider() { ... override fun query(...): Cursor { val appContext = context?.applicationContext ?: throw IllegalStateException() val hiltEntryPoint = EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint::class.java) val analyticsService = hiltEntryPoint.analyticsService() ... } }
자바
public class ExampleContentProvider extends ContentProvider { @Override public Cursor query(...) { Context appContext = getContext().getApplicationContext(); ExampleContentProviderEntryPoint hiltEntryPoint = EntryPointAccessors.fromApplication(appContext, ExampleContentProviderEntryPoint.class); AnalyticsService analyticsService = hiltEntryPoint.analyticsService(); } }
이 예에서는 진입점이 SingletonComponent
에 설치되어 있으므로 ApplicationContext
를 사용하여 진입점을 검색해야 합니다. 검색하려는 결합이 ActivityComponent
에 있다면 ActivityContext
를 대신 사용합니다.
Hilt 및 Dagger
Hilt는 Dagger 종속 항목 삽입 라이브러리를 기반으로 빌드되어 Dagger를 Android 애플리케이션에 통합하는 표준 방법을 제공합니다.
Dagger와 관련하여 Hilt의 목표는 다음과 같습니다.
- Android 앱을 위한 Dagger 관련 인프라 간소화
- 앱 간의 설정, 가독성 및 코드 공유를 용이하게 하기 위한 표준 구성요소 및 범위 세트 생성
- 테스트, 디버그 또는 출시와 같은 다양한 빌드 유형에 서로 다른 결합을 프로비저닝하는 쉬운 방법 제공
Android 운영체제는 많은 자체 프레임워크 클래스를 인스턴스화하므로 Android 앱에서 Dagger를 사용하려면 상당한 양의 상용구를 작성해야 합니다. Hilt는 Android 애플리케이션에서 Dagger 사용과 관련된 상용구 코드를 줄입니다. Hilt는 자동으로 다음을 생성하고 제공합니다.
- 달리 수동으로 생성해야 하는 Dagger와 Android 프레임워크 클래스를 통합하기 위한 구성요소
- Hilt가 자동으로 생성하는 구성요소와 함께 사용할 범위 주석
Application
또는Activity
와 같은 Android 클래스를 나타내는 사전 정의된 결합@ApplicationContext
및@ActivityContext
를 나타내는 사전 정의된 한정자
Dagger 및 Hilt 코드는 동일한 코드베이스에 공존할 수 있습니다. 그러나 대부분의 경우 Android에서 Dagger의 모든 사용을 관리하려면 Hilt를 사용하는 것이 가장 좋습니다. Dagger를 사용하는 프로젝트를 Hilt로 이전하려면 이전 가이드 및 Hilt로 Dagger 앱 이전 Codelab을 참조하세요.
추가 리소스
Hilt에 관해 자세히 알아보려면 다음 추가 리소스를 참조하세요.