After reading the answer by @vaughandroid, and What determines the lifecycle of a component (object graph) in Dagger 2? I think I understand custom scopes well enough to answer my own question.
First, here are a couple rules when dealing with components, modules, and scoping annotations in dagger2.
- A Component must have a (single) scope annotation (e.g.
@Singleton
or @CustomScope
).
- A Module does not have a scope annotation.
- A Module Method may have a (single) scope that matches its Component or no scope, where:
- Scoped: means a single instance is created for each instance of the component.
- Unscoped: mean a new instance is created with each inject() or provider call
- NOTE: Dagger2 reserves
@Singleton
for the root Component (and it's modules) only. Subcomponents must use a custom scope, but the functionality of that scope is exactly the same as @Singleton
.
Now, to answer the question: I would say create a new named scope for each conceptually different scope. For example, create a @PerActivity
, @PerFragment
, or @PerView
annotation that indicates where the component should be instantiated, and thus indicating its lifetime.
Note: this is a compromise between two extremes. Consider the case of a root component and n subcomponents you will need:
- at least 2 annotations (
@Singleton
and @SubSingleton
), and
- at most n+1 annotations (
@Singleton
, @SubSingleton1
, ... @SubSingletonN
).
Example:
Application:
/** AppComponent.java **/
@Singleton
@Component( modules = AppModule.class )
public interface AppComponent{
void inject(MainActivity mainActivity);
}
/** AppModule.java **/
@Module
public class AppModule{
private App app;
public AppModule(App app){
this.app = app;
}
// For singleton objects, annotate with same scope as component, i.e. @Singleton
@Provides @Singleton public App provideApp() { return app; }
@Provides @Singleton public EventBus provideBus() { return EventBus.getDefault(); }
}
Fragment:
/** Fragment1Component.java **/
@PerFragment
@Component( modules = {Fragment1Module.class}, dependencies = {AppComponent.class} )
public interface Fragment1Component {
void inject(Fragment1 fragment1);
}
/** Fragment1Module.java **/
@Module
public class Fragment1Module {
// For singleton objects, annotate with same scope as component, i.e. @PerFragment
@Provides @PerFragment public Fragment1Presenter providePresenter(){
return new Fragment1Presenter();
}
}
/** PerFragment.java **/
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerFragment {}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…