Android Dagger
DI와 ioC
Dagger는 DI Framework 입니다.
DI는 Dependency Injection(의존성 주입)의 준말입니다.
의존성 주입이란 외부에서 의존 객체를 생성하여 넘겨주는것을 의미.
DI를 위해서는 객체를 생성하고 넘겨주는 외부의 무언가가 필요합니다.
이것이 DI Framework가 하는 일입니다.
외부에서 넘겨주는 무언가를 스프링에서는 컨테이너,
Dagger에서는 Component와 Module이라고 부릅니다.
DI는 이렇게 의존성이 있는 객체의 제어를 외부 Framework로 올리면서 IoC개념을 구현합니다.
Ioc는 Inversion of Control(제어의 역전)의 준말입니다.
:외부 컨테이너가 객체를 생성, 주입합니다.
제어가 거꾸로 가는 개념을 IoC라 하고,
DI는 IoC를 구현하는 방법 중 하나입니다.
DI는 왜 필요할까?
1. 의존성 파라미터를 생성자에 작성하지 않아도 되므로 보일러 플레이트 코드를 많이 줄일 수 있습니다.
boilerplate code:
-최소한의 변경으로 재사용할 수 있는것
-적은 수정만으로 여러 곳에 활용 가능한 코드, 문구
-각종 문서에서 반복적으로 인용되는 문서의 한 부분
반복되지만 자주쓰이는 형태를 자동화한다는게 보일러플레이트의 핵심이다.
2. Interface에 구현체를 쉽게 교체하면서 상황에 따라 적절한 행동을 정의 할 수 있습니다.
이것은 특히 Mock객체와 실제 객체를 바꿔가며 테스트 할 때 유용합니다.
Dagger 기본개념
1. Inject
2. Component
3. Subcomponent
4. Module
5. Scope
Inject
의존성 주입을 요청합니다.
Inject 어노테이션으로 주입을 요청하면 연결된 Component가 Module로 부터 객체를 생성하여 넘겨줍니다.
Component
연결된 Module을 이용하여 의존성 객체를 생성하고, Inject로 요청받은 인스턴스에 생성한 객체를 주입합니다.
의존성을 요청받고 주입하는 Dagger의 주된 역할을 수행합니다.
Subcomponent
Component는 계층 관계를 만들 수 있습니다.
Subcomponent는 Inner Class방식의 하위계층 Componenet입니다.
Sub의 Sub도 가능합니다.
Inject로 주입을 요청받으면 Subcomponent에서 먼저 의존성을 검색하고, 없으면 부모로 올라가면서 검색합니다.
Module
Component에 연결되어 의존성 객체를 생성합니다.
생성 후 Scope에 따라 관리도 합니다.
Scope
생성된 객체의 Lifecycle범위입니다.
@Inject -> Subcomponent -> Module -> Scope에 있으면 return 없으면 생성
Subcomponent Module에서 -> Module -> Scope에 있으면 return 없으면 생성
맞는 타입을 못찾으면 상위 Component
Dagger 사용하기
1. Application Component (실제 앱에서 사용시 AppComponent를 생성해서 사용한듯.)
@Singleton //Scope
//연결할 Module을 정의합니다.
@Component(modules = {
AndroidSupportInjectionModule.class,
ActivityBindingModule.class,
ApplicationModule.class
})
//Application과의 연결을 도울 AndroidInjector를 상속받고, 제네릭으로 Application클래스를 정의합니다.
public interface Appcomponent extends AndroidInjector<BaseApplication>{
//Application과의 연결을 도울 Builder를 정의합니다.
@Component.Builder
interface Builder{
@BindsInstance
Appcomponent.Builder application(Application application);
AppComponent build();
}
}
Application Module
@Module
public class ApplicationModule{
//Context 타입의 의존성 객체를 생성합니다.
@Provides
Context providesContext(Application application){
return application;
}
}
Provides어노테이션으로 의존성 객체를 생성할 메소드를 정의합니다.
반환 타입을 따라 Component가 검색하여 활용합니다.
Application클래스에서 Component연동하기
//DaggerApplication을 상속받고, ApplicationComponent에서 정의한 Builder를 활용하여 Component와 연결합니다.
public class BaseApplication extends DaggerApplication{
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector(){
return DaggerAppComponent.builder().application(this).build();
}
}
ActivitySubcomponent생성하기
//ActivityBindingModule은 위 ApplicationComponent에 연결되어 있습니다.
@Module
public abstract class ActivityBindingModule{
//ContributesAndroidInjector 어노테이션을 달고 반환타입을 통해 해당 Activity의 Subcomponent를 생성합니다.
//modules에 Subcomponent와 연결할 Module을 정의합니다. 이 Module들이 실제 의존성 객체를 생성합니다.
@ActivityScoped //Scope
@ContributesAndroidInjector(modules = TaskModule.class)
abstract TaskActivity taskActivity();
@ActivityScoped
@ContributesAndroidInjector(modules = TaskDetailPresenterModule.class)
abstract TaskDetailActivity taskDetailActivity();
}
원래 Subcomponent는 어노테이션을 활용하여 직접 만들어야 했지만, 이제 ContributesAndroidInjector를 활용하여 Module에서 자동으로 생성할 수 있습니다.
ActivitySubcomponent의 Module
@Module
public abstract class TaskModule{
//ContributesAndroidInjector로 FragmentSubcomponent를 생성합니다.
@FragmentScoped //Scope
@ContributesAndroidInjector
abstract TaskFragment taskFragment();
//TaskPresenter 타입의 의존성 객체를 생성합니다.
@ActivityScoped
@Provides
static TaskPresenter taskPresenter(){
return new TaskPresenter();
}
}
ApplicationModule와 마찬가지로 Provides으로 의존성 객체를 생성할 메소드를 정의합니다.
그리고 ContributesAndroidInjector로 하위 Fragment의 Subcomponent를 생성합니다.
Activity에서 Component연동하기
//DaggerAppCompatActivity를 상속받아 Component를 연결합니다.
public class TasksActivity extends DaggerAppCompatActivity{
//TaskPresenter 타입의 의존성 주입을 요청합니다.
@Inject
TasksPresenter mTasksParesenter;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.tasks_act);
}
}
TaskPresenter의존성을 요청하면 TasksActivity와 연결된 TasksModule에서 생성하고, Subcomponent에서 주입합니다.
TasksModule은 ActivityBindingModule에서 Subcomponent를 생성하면서 modules로 연결 하였습니다.
Fragment에서 Component연동하기
//DaggerFragment를 상속받아 Component를 연결합니다.
@ActivityScoped //Fragment는 Activity에 속하므로 Activity Scope를 정의하였습니다.
public class TaskFragment extends DaggerFragment{
//TasksContract.Presenter 타입의 의존성 주입을 요청합니다.
@Inject
TasksContract.Presenter mPresenter;
}
참조 :
'안드로이드' 카테고리의 다른 글
[Android] Dependency, Dependency Injection (0) | 2022.10.27 |
---|---|
[Android] DI란?, Dagger2 사용법에 대해 알아보자 (0) | 2022.10.27 |
[Android] Context에 대해 알아보자 (0) | 2022.10.27 |
[Android] 데이터 바인딩 BindingAdapter (0) | 2022.10.27 |
[Android] Android Apk 패키징 v1, v2 (0) | 2022.10.27 |