https://dagger.dev/hilt/entry-points
5.5 Core APIs – Entry Points
Entry point란 무엇인가?
Entry point(진입점)는 Dagger를 사용하여 의존성 주입을 할 수 없는 코드에서 제공된 Dagger 객체를 얻을 수 있는 방법이다. Dagger가 관리 하는 오브젝트 그래프에 코드가 처음 들어가는 지점이다.
만약 Dagger 컴포넌트에 익숙하다면, Entry point는 Hilt가 상속하여 생성할 컴포넌트의 인터페이스다.
Entry point는 언제 필요할까?
Dagger를 적용하지 않은 라이브러리를 인터페이싱 하거나 Hilt에서 지원하지 않는 안드로이드 구성요소가 Dagger 객체에 접근이 필요할 때 Entry point가 필요하다.
일반적으로, 대부분의 entry point는 Activity, Fragment 와 같은 안드로이드 플랫폼이 인스턴스화 하는 곳에서 필요하다. @AndroidEntryPoint는 Entry point들을 다루기 위해 특화된 도구이며 안드로이드 클래스의 Entry point에 접근할 수 있도록 한다. 이 작업은 이미 해당 안드로이드 클래스들에서는 특별히 다루고 있기 때문에, 다음 나올 문서에서는 다른 타입의 클래스에 Entry point가 필요한 경우를 다룬다.
Entry Point, 어떻게 사용하나?
EntryPoint 생성하기
Entry point를 생성하기 위해서는 각 바인딩 타입에 대한 접근 가능한 메서드를 사용하여 인터페이스를 정의하고 @EntryPoint 어노테이션을 추가해야 한다. 그런 다음 @InstallIn을 추가하여 Entry point가 설치될 컴포넌트를 지정한다.
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface FooBarInterface {
@Foo fun getBar(): Bar
}
EntryPoint에 접근하기
Entry point에 접근하기 위해서는 EntryPoints클래스를 사용하여 컴포넌트 인스턴스를 매개변수로 전달하거나 컴포넌트 홀더 역할을 하는 @AndroidEntryPoint 객체를 전달한다. 매개변수로 전달하는 컴포넌트가 @EntryPoint 인터페이스에 추가되어 있는 @InstallIn 어노테이션이 전달하는 컴포넌트와 일치하는지 확인하자.
앞에서 정의한 Entry point 인터페이스를 사용하는 방법은 다음과 같다.
val bar = EntryPoints.get(applicationContext, FooBarInterface::class.java).getBar()
추가적으로 EntryPointAccessors의 메서드는 표준 안드로이드 컴포넌트로부터 Entry point들을 가져오는것에 대해 더 적합하며 타입에 안전하다.
모범 사례 : Entry point 인터페이스는 어디에 정의해야 할까?
만약 Hilt를 사용하지 않는 라이브러리 그리고 Dagger로부터 Foo 클래스를 필요로 하는 클래스 인스턴스화를 구현해야한다면, Entry point 인터페이스는 사용하고 있는 클래스 또는 Foo와 함께 정의 되어야 할까?
일반적으로 해당 클래스가 Foo 아닌 Entry point 인터페이스를 필요로 한다면, Entry point를 사용하고 있는 클래스와 함께 정의되는 것이 맞다. 해당 클래스에 더 많은 의존성이 필요하면, 추가 메서드를 Entry point 인터페이스에 쉽게 추가하여 가져 올 수 있다. 본질적으로 Entry point 인터페이스는 해당 클래스의 @Inject 생성자의 위치에서 기능을 하게 된다. 대신 Entry point가 Foo에 정의 된 경우 다른 사람들이 Foo를 주입하거나 Entry point 인터페이스를 사용해야 하는지 혼동 될 수 있다. 또한 나중에 다른 의존성이 필요한 경우 더 많은 Entry point 인터페이스가 추가 될 수 있다.
모범 사례
// Dagger에서 인스턴스화되지 않기 때문에 @Inject가 없다.
class MyClass : NonHiltLibraryClass() {
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface MyClassInterface {
fun getFoo(): Foo
fun getBar(): Bar
}
fun doSomething(context: Context) {
val myClassInterface =
EntryPoints.get(applicationContext, MyClassInterface::class.java)
val foo = myClassInterface.getFoo()
val bar = myClassInterface.getBar()
}
}
안 좋은 사례
@Module
@InstallIn(ApplicationComponent::class)
object FooModule {
@Provides
fun provideFoo(): Foo {
return Foo()
}
@EntryPoint
@InstallIn(ApplicationComponent::class)
interface FooInterface {
fun getFoo(): Foo
}
}
0개의 댓글