① 만약 A 클래스에서 B 클래스의 인스턴스를 생성할 때 생성자에 C 클래스의 인스턴스를 넘겨줘야 한다면 Dagger 의 생성자 주입을 사용하여 자동으로 B 클래스의 생성자에 C 클래스의 인스턴스를 주입할 수 있습니다.(예: MainActivity(A)에서 ViewModel 인스턴스(B)를 생성할 때 생성자에 UseCase 인스턴스(C)를 넣는 것).
② 이 글에서는 Dagger 가 생성한 코드를 기반으로 생성자 주입 시 작업 흐름에 대해 작성하였습니다.
③ 예제 코드는 아래와 같습니다.
Component interface
@Component(modules = [CarModule::class])
interface CarComponent {
fun getCar(): Car
}
Component 와 연결된 Module class
@Module
class CarModule {
@Provides
fun provideCar(engine: Engine): Car {
return Car(engine)
}
@Provides
fun provideEngine(): Engine {
return Engine()
}
}
생성자 주입을 받을 class
class Car @Inject constructor(private val engine: Engine) {
fun drive() {
engine.start()
}
}
주입할 인스턴스의 class
class Engine {
fun start() {
Log.d("Dagger2Test", "Engine start")
}
}
생성자 주입을 요청하고 생성자 주입된 인스턴스를 사용하는 class
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val component = DaggerCarComponent.create()
val car = component.getCar()
car.drive()
}
}
④ 생성자 주입시 작업 흐름
⑴. MainActivity 클래스에서 Component 의 Provision Method 를 호출하여 생성자 주입 작업을 트리거합니다.
private static final class CarComponentImpl implements CarComponent {
private final CarModule carModule;
private final CarComponentImpl carComponentImpl = this;
private CarComponentImpl(CarModule carModuleParam) {
this.carModule = carModuleParam;
}
//1. Component 의 Provision Method 를 호출합니다.
@Override
public Car getCar() {
return CarModule_ProvideCarFactory.provideCar(carModule, CarModule_ProvideEngineFactory.provideEngine(carModule));
}
}
⑵. Car 클래스의 생성자에는 Engine 클래스의 인스턴스가 매개변수로 넘어가야 하기 때문에 Dagger 에서 Car 인스턴스를 만들기 전에 ProvideFactory 클래스의 static 메서드를 통해 Engine 인스턴스를 연결된 Module 에게 요청합니다.
public static Engine provideEngine(CarModule instance) {
return Preconditions.checkNotNullFromProvides(instance.provideEngine());
}
⑶. 주입할 인스턴스(Engine)를 생성하였으므로 주입받을 인스턴스를 생성하기 위해 ProvideFactory 클래스의 static 메서드를 호출하여 연결된 Module 에게 Car 인스턴스를 요청합니다. 이때 주입받을 인스턴스(Car)의 생성자에 의존성 주입(Engine)이 발생합니다.
public static Car provideCar(CarModule instance, Engine engine) {
return Preconditions.checkNotNullFromProvides(instance.provideCar(engine));
}
⑷. Provision Method 에서 생성자 주입이 완료된 인스턴스의 참조를 반환합니다.
@Override
public Car getCar() {
return CarModule_ProvideCarFactory.provideCar(carModule, CarModule_ProvideEngineFactory.provideEngine(carModule));
}
⑤ 요약
외부 클래스에서(예: MainActivity) Component 의 Provision Method 를 호출하여 생성자 주입이 되어야하는 인스턴스(예: Car)를 요청하면 먼저 Dagger 에서 생성한 ProvideFactory 클래스의 static 메서드에서 Component 와 연결된 Module 을 통해 주입되어야 하는 인스턴스(예: Engine)를 가져온 후 생성자 주입을 받아야 하는 인스턴스(예: Car)를 연결된 Module 에게 요청할 때 주입되어야 하는 인스턴스(예: Engine)를 함께 전달하여 생성자에 의존성 주입이 완료된 인스턴스를 반환받아서 외부 클래스(예: MainActivity)의 Component 호출부에 반환합니다.
'dagger' 카테고리의 다른 글
Dagger2 with ViewModel (1) | 2022.12.29 |
---|---|
Dagger2 Singleton (0) | 2022.12.03 |
Dagger2 필드 주입 (0) | 2022.11.24 |
Dagger2 시작 (0) | 2022.11.22 |