Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발자이야기

dagger @binds 어노테이션 본문

android

dagger @binds 어노테이션

개발자가되고싶어 2021. 5. 23. 13:27
@Provides 와 @Binds 어노테이션의 차이

 

 

@Provides

 

우선 @Provides 어노테이션을 확인해 보자

@Module
abstract class CarModule2 {

    @Provides
    fun provideEngine(): Engine {
        return LPG()
    }
}

 

provideEngine 이라는 함수명을 갖고 있고 (함수명은 마음대로) 리턴 타입은 Engine 이며

return LPG 객체를 생성하여 반환하게 되어있다. 여기서 Engine 은 interface 이다

 

class LPG : Engine {
    override fun engine(): String {
        return "LPG엔진"
    }
}

LPG 객체는 위와같은 클래스로 되어있다. 단순 Engine interface를 구현한 구현체 이다.

 

@Provides 를 사용했을때 컴파일 과정에서 생성되는 코드를 한번 확인해보자

private Car injectCar(Car instance) {
  Car_MembersInjector.injectEngine(instance, CarModule_ProvideEngineFactory.provideEngine(carModule));
  return instance;
}

위의 코드에서 보면 Car_MembersInjector.injectEngine 주입해 주는 과정에서 

(instance, CarModule_ProvideEngineFactory.provideEngine(carModule) )

위의 CarModule_ProvideEngineFactory 클래스에서 엔진을 얻어오는 클래스 파일이 하나 생성되었다.

생성된 코드는 아래와 같다

public final class CarModule_ProvideEngineFactory implements Factory<Engine> {
  private final CarModule module;

  public CarModule_ProvideEngineFactory(CarModule module) {
    this.module = module;
  }

  @Override
  public Engine get() {
    return provideEngine(module);
  }

  public static CarModule_ProvideEngineFactory create(CarModule module) {
    return new CarModule_ProvideEngineFactory(module);
  }

  public static Engine provideEngine(CarModule instance) {
    return Preconditions.checkNotNull(instance.provideEngine(), "Cannot return null from a non-@Nullable @Provides method");
  }
}

위의 생성된 클래스를 기억해 보자. 위의 클래스가 @Binds 를 사용했을땐 통째로 사라진다.

@Provides 어노테이션을 사용했을때 생성되는 파일을 간단하게 알아봤다.

 

 

@Binds

@Binds 어노테이션을 사용했을때를 한번 알아보자.

@Module
abstract class CarModule2 {

    @Binds
    abstract fun bindEngine(engine: LPG): Engine
}

 

@Binds 어노테이션 의 사용에는 제약이 있다. abstract 함수를 사용해야 하며, 하나의 구현체를 인자로 받아야 한다.

우선 인자로 받은 LPG 클래스를 확인해 보자

class LPG @Inject constructor() : Engine {
    override fun engine(): String {
        return "LPG엔진"
    }
}

LPG 클래스에 constructor 생성자 앞에 @Inject 어노테이션을 붙여 줌으로써 Dagger에게 생성자 주입을 할것이다 라고 알려줘야 한다. 생성자 주입을 Dagger 에게 알려 주었기 때문에 @Binds 를 사용한 함수에서 LPG 인자를 받을 수 있는것이다.

 

이제 @Binds 어노테이션을 활용했을때 컴파일 과정에서 생성되는 코드를 한번 보자

private Car injectCar(Car instance) {
  Car_MembersInjector.injectEngine(instance, new LPG());
  return instance;
}

위의 코드를 @Provides 어노테이션을 사용했을때의 코드와 비교해 보자.

 

@Provides 사용할 때
private Car injectCar(Car instance) {
  Car_MembersInjector.injectEngine(instance, CarModule_ProvideEngineFactory.provideEngine(carModule));
  return instance;
}

@Binds 사용할 때
private Car injectCar(Car instance) {
  Car_MembersInjector.injectEngine(instance, new LPG());
  return instance;
}

 

위의 코드를 확인해 보면 @Binds 를 사용했을때 컴파일 과정의 코드에선 단순히 new LPG 객체의 인스턴스를 사용하려는 곳의 Engine에 주입시켜 주고 있다.

@Provides 에서 설명했던 CarModule_ProvideEngineFactory 클래스 파일이 통째로 사라졌다!!

 

@Binds 를 사용했을때 @Provides를 사용 했을 때 보다 코드의 양이 40%정도가 감소된다고 한다.

자세한 내용은 https://medium.com/mobile-app-development-publication/dagger-2-binds-vs-pro 참조

 

직접 컴파일 해보며 테스트 해보며 이해해 보는걸 추천드립니다.

소스는 여기에 https://github.com/boidmy/dagger-Binds

 

boidmy/dagger-Binds

Contribute to boidmy/dagger-Binds development by creating an account on GitHub.

github.com

(저도 아직 공부중이라 미흡할 수 있는점 양해 부탁드립니다.)

 

언제든 지적과 피드백 환영합니다!

 

 

'android' 카테고리의 다른 글

mvvm + dagger  (0) 2021.06.07
android AAC LiveData - switchMap, map  (0) 2021.05.28
의존성주입(DI) android dagger  (0) 2021.05.22
android recyclerview diffutil  (0) 2021.05.14
Retrofit2 url이 만들어지는 패턴  (0) 2020.06.02