본문 바로가기

dagger

Dagger2 필드 주입

① 앞의 글에서 작성한 생성자 주입은 특정 객체를 생성할 때 생성자의 매개변수를 통해 객체를 주입하는 것이고, 이번 글에서 작성할 필드 주입은 이미 생성되어있는 객체의 필드에 객체를 주입하기 위해 사용할 수 있는 방법입니다.

 

② Andorid 에서는 Activity 와 같은 컴포넌트 객체는 개발자가 직접 생성하는 것이 아니라 Android 시스템에서 객체를 생성하여 생명주기를 관리합니다. 그렇기 때문에 Activity 와 같은 Android 컴포넌트에 특정 객체를 주입하기 위해서는 생성자 주입이 아닌 필드 주입을 사용하여야 합니다.(생성자 주입을 하기 위해서는 Dagger 에서 해당 객체를 직접 생성해야 하는데 그것이 불가능하기 때문에)

 

③ 이 글에서는 Dagger 가 생성한 코드를 기반으로 필드 주입 시 작업 흐름에 대해 작성하였습니다.

 

④ 예제 코드는 아래와 같습니다.

Component interface

@Component(modules = [CarModule::class])
interface CarComponent {
    fun inject(activity: MainActivity)
}

 

Component 와 연결된 Module class

@Module
class CarModule {
    @Provides
    fun provideCar(): Car {
        return Car()
    }
}

 

필드에 주입될 class

class Car {
    fun drive() {
        Log.d("Dagger2", "drive() call")
    }
}

 

Dagger 에 의해 필드 주입을 받을 class

class MainActivity : AppCompatActivity() {
    @Inject
    lateinit var car: Car

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val component = DaggerCarComponent.create()
        component.inject(this)
        car.drive()
    }
}

 

⑤ 필드 주입 시 작업 흐름

  ⑴ MainActivity 클래스에서 Component 의 Member-Injection Method 를 호출하여 필드 주입을 트리거합니다.

@Override
public void inject(MainActivity activity) {
  injectMainActivity(activity);
}

private MainActivity injectMainActivity(MainActivity instance) {
  MainActivity_MembersInjector.injectCar(instance, CarModule_ProvideCarFactory.provideCar(carModule));
  return instance;
}

 

  ⑵ Dagger 에서 생성한 ProvideFactory 클래스에서 Component 와 연결된 Module 을 통해 주입해야 할 클래스의 인스턴스를 가져옵니다.

public static Car provideCar(CarModule instance) {
  return Preconditions.checkNotNullFromProvides(instance.provideCar());
}
@Provides
fun provideCar(): Car {
    return Car()
}

 

  ⑶ Dagger 에서 생성한 MemberInjector 클래스의 "Component 메서드명 + 주입할 인스턴스 타입" 형태의 static 메서드를 호출합니다. 이 메서드에서 실제로 필드 주입이 발생합니다. 이때 첫번째 매개변수는 주입받을 인스턴스이고 두번째 매개변수는 주입할 인스턴스입니다.

@InjectedFieldSignature("com.dagger2test.MainActivity.car")
public static void injectCar(MainActivity instance, Car car) {
  instance.car = car;
}

 

⑤ 요약

외부 클래스(예: MainActivity)에서 Component 에 정의된 Member-Injection Method 를 호출하여 필드 주입을 트리거하면 가장 먼저 주입해야 할 인스턴스(예: Car)를 생성합니다. 그 다음 Dagger 에서 생성한 MemberInjector 클래스의 "Component 메서드명 + 주입할 인스턴스 타입"의 static 메서드(예: injectCar)에 주입받을 인스턴스와 주입할 인스턴스를 매개변수로 전달하며 호출합니다. 마지막으로 static 메서드에서 첫번째 매개변수를 통해 받은 인스턴스에 @Inject 어노테이션이 선언되어있는 필드에 두번째 매개변수 참조를 저장하며 필드 주입을 완성합니다. 

 

'dagger' 카테고리의 다른 글

Dagger2 with ViewModel  (1) 2022.12.29
Dagger2 Singleton  (0) 2022.12.03
Dagger2 생성자 주입  (0) 2022.11.23
Dagger2 시작  (0) 2022.11.22