Dagger 2의 스코프, 특히 스코프 그래프의 수명주기를 둘러 보려고합니다. 범위를 벗어날 때 정리할 구성 요소를 어떻게 작성합니까?
Android 애플리케이션의 경우 Dagger 1.x를 사용하는 경우 일반적으로 활동 레벨에서 하위 범위를 작성하도록 확장 할 애플리케이션 레벨에 루트 범위가 있습니다.
public class MyActivity {
private ObjectGraph mGraph;
public void onCreate() {
mGraph = ((MyApp) getApplicationContext())
.getObjectGraph()
.plus(new ActivityModule())
.inject(this);
}
public void onDestroy() {
mGraph = null;
}
}
하위 범위는 참조를 유지하는 한 존재했으며,이 경우 활동의 수명주기였습니다. onDestroy에서 참조를 삭제하면 범위가 지정된 그래프를 가비지 수집 할 수 있습니다.
편집하다
Jesse Wilson은 최근 mea culpa를 게시했습니다.
Dagger 1.0은 범위 이름을 잘못 정돈했습니다 ... @Singleton 주석은 루트 그래프와 사용자 정의 그래프 모두에 사용되므로 사물의 실제 범위가 무엇인지 알아내는 것이 까다 롭습니다.
그리고 내가 읽은 모든 것은 Dagger 2에 대한 요점이 스코프 작동 방식을 개선하지만 그 차이점을 이해하기 위해 고심하고 있습니다. 아래의 @Kirill Boyarshinov의 의견에 따르면 구성 요소의 수명주기 또는 종속성은 평소와 같이 구체적인 참조로 결정됩니다. 그렇다면 Dagger 1.x와 2.0 스코프의 차이점은 순전히 의미 명확성의 문제입니까?
내 이해
단검 1.x
의존성은 어느 쪽이든 아니든간에 요 @Singleton
. 루트 그래프와 하위 그래프의 종속성에 대해서도 동일하게 적용되므로 종속성이 바인딩 된 그래프에 대한 모호함이 발생합니다 ( 단어에서 하위 그래프 내에 단일 톤이 캐시되어 있거나 새 활동 하위 그래프 일 때 항상 다시 작성 됨 참조). 건설 되었습니까? )
단검 2.0
사용자 지정 범위를 사용하면 의미 적으로 명확한 범위를 만들 수 있지만 기능적 @Singleton
으로 Dagger 1.x 에 적용하는 것과 같습니다 .
// Application level
@Singleton
@Component( modules = MyAppModule.class )
public interface MyAppComponent {
void inject(Application app);
}
@Module
public class MyAppModule {
@Singleton @Named("SingletonScope") @Provides
StringBuilder provideStringBuilderSingletonScope() {
return new StringBuilder("App");
}
}
// Our custom scope
@Scope public @interface PerActivity {}
// Activity level
@PerActivty
@Component(
dependencies = MyAppComponent.class,
modules = MyActivityModule.class
)
public interface MyActivityComponent {
void inject(Activity activity);
}
@Module
public class MyActivityModule {
@PerActivity @Named("ActivityScope") @Provides
StringBuilder provideStringBuilderActivityScope() {
return new StringBuilder("Activity");
}
@Name("Unscoped") @Provides
StringBuilder provideStringBuilderUnscoped() {
return new StringBuilder("Unscoped");
}
}
// Finally, a sample Activity which gets injected
public class MyActivity {
private MyActivityComponent component;
@Inject @Named("AppScope")
StringBuilder appScope
@Inject @Named("ActivityScope")
StringBuilder activityScope1
@Inject @Named("ActivityScope")
StringBuilder activityScope2
@Inject @Named("Unscoped")
StringBuilder unscoped1
@Inject @Named("Unscoped")
StringBuilder unscoped2
public void onCreate() {
component = Dagger_MyActivityComponent.builder()
.myApplicationComponent(App.getComponent())
.build()
.inject(this);
appScope.append(" > Activity")
appScope.build() // output matches "App (> Activity)+"
activityScope1.append("123")
activityScope1.build() // output: "Activity123"
activityScope2.append("456")
activityScope1.build() // output: "Activity123456"
unscoped1.append("123")
unscoped1.build() // output: "Unscoped123"
unscoped2.append("456")
unscoped2.build() // output: "Unscoped456"
}
public void onDestroy() {
component = null;
}
}
사용 @PerActivity
하는 것이 당신의 의도 를 전달 한다는 것 하면이 구성 요소의 수명주기에 대한 있지만 궁극적으로 언제 어디서나 구성 요소를 사용할 수 있습니다. Dagger의 유일한 약속은 주어진 컴포넌트에 대해 범위 어노테이션이있는 메소드가 단일 인스턴스를 리턴한다는 것입니다. 또한 Dagger 2가 구성 요소의 범위 주석을 사용하여 모듈이 범위가 같거나 범위가 아닌 종속성 만 제공하는지 확인합니다.
요약해서 말하자면
종속성은 여전히 싱글 톤 또는 비 싱글 톤이지만 @Singleton
이제 응용 프로그램 수준의 싱글 톤 인스턴스를위한 것이며 사용자 지정 범위는 수명주기가 짧은 싱글 톤 종속성에 주석을 추가하는 데 선호되는 방법입니다.
개발자는 더 이상 필요하지 않은 참조를 삭제하여 구성 요소 / 종속성의 수명주기를 관리하고 구성 요소가 의도 한 범위 내에서 한 번만 생성되도록해야하지만 사용자 지정 범위 주석을 사용하면 해당 범위를 쉽게 식별 할 수 있습니다. .
$ 64k 질문 *
Dagger 2 범위 및 라이프 사이클에 대한 이해가 정확합니까?
* 실제로 $ 64'000 질문이 아닙니다.
plus()
새 그래프에 대한 참조를 사용하여 Application 레벨 ObjectGraph 오브젝트를 서브 그래프 할 때 활동에 저장되었으며 라이브 사이클에 바인드되었습니다 (에서 참조 됨onDestroy
). 범위는 컴파일 타임에 모든 종속성을 충족하면서 오류없이 구성 요소 구현이 생성되도록합니다. 따라서 문서화 목적만을위한 것이 아닙니다. 이 스레드 에서 몇 가지 예를 확인하십시오 .