Android/App개발2019.06.10 14:15

대거2를 적용하는 3 가지 방법이 있다.

 

1번은 Component, Module, Scope으로 직접 모두 기술하는 방법이고

2번은 DispatchingAndroidInjector로 제공하는 방법

3번은 안드로이드에서 제공하는 기반클래스(DaggerActivity, DaggerFragment, ...)로 제공하는 방법이 있다.

 

여기서는 1번 방식으로 작업하는 방식을 설명한다.

여러가지 구성을 하는 방법이 있겠지만 내가 작업한 방식을 설명한다. 틀린 부분이 있다면 누구든 지적을 해주었으면 한다.

 

안드로이드에서 대거는 전역 및 로컬범위로 다양하게 scope을 지정하여 객체를 주입할 수 있다.

Application레벨은 보통 전역 객체를 Activity레벨은 로컬객체를 주입한다.

 

전역에서 GuiManager를 로컬에서 ItemAdapter를 주입할것이다. 

 

Module을 정의한다.

 

in AppModule.java

 

@Module

public class AppModule {

  private MyApplication mApp;

  public AppModule(MyApplication app) { mApp = app; }

  

  @Provides

  @Singletone

  GuiManager provideGuiManager() { return new GuiManager(); }

}

 

MyApplication을 멤버로 가지고 있으며 Scope을 Singletone으로 GuiManager를 주입하기 위한 Provider를 구현한다.

provide를 prefix로 하여 메서드를 정의하며 해당 클래스의 인스턴스를 생성하여 반환한다.

 

Component를 구현한다.

 

in AppComponent

 

@Singletone

@Component(modules = { AppModule.class }

public interface AppComponent {

  void inject(MyApplication app);

  void inject(MainActivity activity);

}

 

Application에서 GuiManager를 주입하는 예이다.

in MyApplication.java

 

public class MyApplication extends Application {

 

  AppComponent mComponent;

 

  @Inject

  protected GuiManager mGuiManager;

 

  @Override

  public void onCreate() {

    super.onCreate();

    mComponent = DaggerAppComponent.builder().appModule(new AppModule()).build();

    mComponent.inject(this);

  }

 

  public AppComponent getComponent() {

    return mComponent;

  }

 

대거는 주석을 기반으로 코드를 생성하며 Dagger를 prefix로하여 Component builder로 객체를 생성할 수 있다. 이렇게 만들어진 ㅡㅐ여component의 inject()를 호출하면 Module에서 provide prefix로 노출한 객체들이 바인딩되어 진다. 

 

이번에는 액티비티 스콥의 주입예이다. ItemAdapter를 MainActivity에서 주입하여 사용할것이다.

 

ActivityModule을 정의한다.

 

@Module

public class ActivityModule {

  private Activity mActivity;

  public ActivityModule(Activity activity) {
    mActivity = activity; 

  }

  

  @Provides @ActivityScope

  Activity activity() { return mActivity; }

 

  @Provides @ActivityScope

  ItemAdapter provideItemAdapter() {

    return new itemAdapter();

  }

}

 

provide prefix로 itemAdapter를 노출하고 있다.

ActivityComponent를 구현한다.

 

@ActivityScope

@Component(dependencies={AppComponent.class}, modules={ActivityModule.class})

public interface ActivityComponent {

  void inject(Activity activity);

}

 

dependencies를 추가하였다. AppComponent를 정의하여 GuiManager도 사용이 가능하다.

MainActivity에서 주입을 시전한다.

 

public class MainActivity extends AppCompatActivity {

  @Inject

  GuiManager guiManager;

  @Inject

  ItemAdapter itemAdapter;

 

  @Override

  public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

 

    ((MyApplication)getApplication()).getComponent().inject(this);

    DaggerActivityComponent activityComponent = DaggerActivityComponent.builder().appComponent(new AppComponent()).build();

    activityComponent.inject(this);

 

    guiManager.showAlert("hi!");

    itemAdapter.setDataSource(new MySource()); 

  }

  ...

}

 

MyApplication의 getComponent()를 가져와서 inject함으로써 GuiManager가 주입되었고 DaggerActivityComponent를 build하여 ItemAdapter를 주입하였다.

이 후 guiManager.showAlert("hi")나 itemAdapter.setDataSource(new MySource()) 같이 주입된 객체를 사용할 수 있다.

guiManager는 singletone의 스콥을 가지며 itemAdapter는 ActivityScope을 가진다.

 

ActivityScope이 무엇인가 싶을텐데.. 아래와 같이 정의된다.

 

@Scope

@Retention(RUNTIME)

public @interface ActivityScope {}

 

Scope을 하나 정의했는데 저리하면 액티비티에 종속되는 범위를 갖는 스콥 아노테이션이 만들어진다. 아노테이션 세계는 참..

 

의존성을 여러개로 나누어서도 관리할 수 있다. 모듈과 콤포넌트를 용도에 맞게 구성하여 사용하면 된다.

이번에는 UserData를 주입하기 위한 예제를 살펴보겠다.

 

@Module

public class UserModule {

  private Activity mActivity;

  public UserModule(Activity act) { mActivity = act; }

 

  @Provides @ActivityScope

  Activity activity() { return mActivity; }

 

  @Provides @ActivityScope

  UserData provideUserData() { reutrn new UserData(); }

}

UserData를 주입하기 위해 provideUserData메서드가 정의되었다.

 

@ActivityScope

@Component(dependencies={AppComponent.class}, modules={ActivityModule.class, UserModule.class})

public interface UserComponent {

  void inject(Activity activity);

}

 

AppComponent, ActivityModule등의 의존성도 포함하고 있으며 주입을 위해 inject가 정의되어 있다.

이 모듈을 사용하기 위해 SubActivity는 다음과 같이 구현된다.

 

public class SubActivity extends Activity {

  @Inject

  ItemAdapter itemAdapter;

  @Inject

  UserData userData;

 

  @Override

  public onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    DaggerActivityComonent.builder().appComponent((MyApplication)getApplication()).getComponent()).build().inject(this);

    DaggerUserData.builder().appComponent((MyApplication)getApplication()).getComponent()).build().inject(this);

  }

  ...

}

 

itemAdapter를 사용하기 위해 DaggerActivityComponent.builder()를 사용했고 userData를 사용하기 위해 DaggerUserData.builder()를 사용했다.

 

이와 같이 전역 및 지역적으로 객체를 주입해서 사용하는 일반적인 방법을 알아 보았다.

 

이 방법은 GuiManager, ItemAdapter, UserData등에 대해 모두 정확히 알고 있어야 하며 코드도 많다. 이 보다 적은 코드로도 적용이 가능한데 위에서 말한대로 두가지 방법이 더 있다. 이 에 대해서는 추가로 공부하여 정리하도록 할것이다.

 

 

 

Posted by 삼스