정상에서 IT를 외치다

[Android, Dagger2] ContributesAndroidInjector 사용해보기 본문

안드로이드

[Android, Dagger2] ContributesAndroidInjector 사용해보기

Black-Jin 2019. 3. 17. 15:38
반응형

안녕하세요. 블랙진입니다.


Di 기본 개념과 Dagger2 사용 예제에 이은 포스팅입니다.


지난 시간 Component 는 모듈에서 제공받은 객체를 어디에 주입할지 정하는 역활을 한다고 했습니다. 


지난 내용

@Component(modules = BurgerModule.class)
public interface BurgerComponent {

void inject(MainActivity activity);
}

보시는 바와 같이 BurgerModule 로 부터 제공받은 객체를 MainActivty 에 주입하는 코드입니다.  MainAcitivty 에서 또한 아래와 같이 DaggerBurgerComponet 를 생성한 후 여기가 주입받을 곳이라는 곳을 코드로 작성해 주어야 합니다.

public class MainActivity extends AppCompatActivity {

@Inject
Burger burger;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

DaggerBurgerComponent.builder().build()
.inject(this);

}
}

만야 위와 같은 객체(Burger)를 다른 엑티비티(ex: DetailActivity)에서 주입 받을러면 어떻게 해야 할까요?


1. Componet 에 주입할 곳을 추가해준다.

@Component(modules = BurgerModule.class)
public interface BurgerComponent {

void inject(MainActivity activity);

//새로 주입할 곳(DetailActivity)을 추가해 주었습니다.
void inject(DetailActivity activity);

}

2. DetailActivity 에서 또한 DaggerBurgerComponet를 생성해 줍니다.

public class DetailActivity extends AppCompatActivity {

@Inject
Burger burger;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("DetailActivity");

DaggerBurgerComponent.builder()
.build().inject(this);

}
}

이렇게 Activity 를 만들 때 마다 Component를 build() 하고 inject() 해주는 방식은 여러모로 귀찮습니다. 이를 좀 더 간단하게 처리해 줄수 있는 방법이 바로 ContributesAndroidInjector를 사용하는 것입니다.



ContributesAndroidInjector?

  • public @interface ContributesAndroidInjector
    Generates an AndroidInjector for the return type of this method. The injector is implemented with a Subcomponent and will be a child of the Module's component.

    This annotation must be applied to an abstract method in a Module that returns a concrete Android framework type (e.g. FooActivityBarFragmentMyService, etc). The method should have no parameters.

    For more information, see the docs

ContributesAndroidInjector


반환 타입을 통해 AndroidInjector 를 생성시켜주는 인터페이스 입니다. SubComponet 를 적용 시켜 사용할 수 있지만 이번 예제에서는 간단한 사용법만 살펴보겠습니다.


1. ActivityBinder

@Module
abstract public class ActivityBinder {

@ContributesAndroidInjector
abstract MainActivity bindMainActivity();

@ContributesAndroidInjector
abstract DetailActivity bindDetailActivity();
}

Module은 필요한 객체를 제공하는 역활을 합니다.


우리는 MainActivity, DetailActivity 에 했던 작업들을 전부 모듈을 사용해 처리할려고 합니다. 그러기 위해서 모듈에 MainActivity와 DetailActivity 를 ContributesAndroidInjector 어노테이션을 사용하여 제공하겠습니다.


2. AppComponent

Component는 모듈에서 제공받은 객체를 조합하여 어디에 주입할지 정하는 역활을 합니다.

@Singleton
@Component(
modules = {
BurgerModule.class,
ActivityBinder.class,
AndroidSupportInjectionModule.class
}
)
public interface AppComponent extends AndroidInjector<MyApplication> {

}

BurgerModule과 ActivityBinder 을 modul에 추가해 주었습니다. 그런데 예제에서 생성하지도 않은 AndroidSupportInjectionModule 이라는게 있습니다. 요건 대거의 안드로이드 지원 모듈로 대거 라이브러리 안에 있습니다. 그리고 AndroidInjector<MyApplication>을 상속함으로서 MyApplication 으로 주입합니다.


3. DaggerApplication

public class MyApplication extends DaggerApplication {

@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().build();
}
}

AndroidInjector을 사용하기 위한 마지막 단계입니다. DaggerApplication 을 상속한 MyApplication 을 맏들어준후 AndroidInjector의 반환값을 설정해 줍니다.

DaggerAppComponet는 대거가 생성해 주는 클래스이므로, 프로젝트를 빌드해야 이 클래스가 생성됩니다. [Build > Make Project] 를 선택한 후 작성해주세요.


4. DaggerAppCompactActivity


MainActivity

public class MainActivity extends DaggerAppCompatActivity {

@Inject
Burger burger;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("MainActivity");

// DaggerBurgerComponent 함수는 필요 없습니다.
/* DaggerBurgerComponent.builder().build()
.inject(this);*/

Log.d("MyTag","MainActivity burger bun : "
+ burger.bun.getBun() + " , patty : " + burger.patty.getPatty());

}
}


DetailActivity

public class DetailActivity extends DaggerAppCompatActivity {

@Inject
Burger burger;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("DetailActivity");

// DaggerBurgerComponent 함수는 필요 없습니다.
/* DaggerBurgerComponent.builder()
.build().inject(this);*/

Log.d("MyTag","DetailActivity burger bun : "
+ burger.bun.getBun() + " , patty : " + burger.patty.getPatty());

}
}

MainActivity, DetailActivity 를 AppCompatActicity 가 아닌 DaggerAppCompatActivity 로 상속해 주면 BurgerComponet 사용 없이 객체를 주입할 수 있게 됩니다. 프로젝트가 점점 커질 수 록 위와 같이 ActivityBinder 을 통해 객체를 어디다 넣을지 관리를 해주면 유지보수에 더욱 큰 장점이 있을거라 생각합니다.


이상 Dagger 에 과한 기본개념 포스팅을 마치겠습니다.

위에 사용한 예제는 링크를 확인해 주세요.


<참고자료>

대거의 안드로이드 문서

Dagger2:AndroidModule

Di 기본개념부터 사용법까지

반응형
Comments