I'm having a similar problem like the one in this question. While the accepted answer does help, but I'm missing final piece to solve the problem.
I have 2 android library modules: common
and exp
which depends on common
.
Everything under common
:
@Module
public class CommonModule {
@Singleton
@Provides
public Repository providesRepository() {
return new Repository();
}
}
@Singleton
@Component(modules={CommonModule.class})
public interface CommonComponent {
void inject(CommonClass commonClass);
/**
CommonClass needs instance of Repository
**/
}
public class CommonDIHolder {
public static CommonComponent sComponent;
public static void init() {
sComponent = DaggerCommonComponent.builder().build();
}
}
Everything under exp
:
@Module(includes={CommonModule.class})
public class ExpModule {
@Singleton
@Provides
public ExpResource provideExpResource() {
return new ExpResource();
}
}
@Singleton
@Component(modules={ExpModule.class}, dependencies={CommonComponent.class})
public interface ExpComponent {
void inject(ExpClass expClass);
/**
ExpClass needs instance of Repository and ExpResource
**/
}
public class ExpDIHolder {
public static ExpComponent sComponent;
public static void init() {
sComponent = DaggerExpComponent.builder()
.commonComponent(CommonDIHolder.sComponent)
.build();
}
}
I need both CommonClass
and ExpClass
receive the same instance of Repository
.
The problem with this approach is that @Singleton
can't depends on @Singleton
. So I have to change the scope of ExpComponent
into self-defined scope called @ExpScope
. Then I changed the provideExpResource
into @ExpScope
as well.
Then I encountered an error saying that ExpComponent
may not reference bindings with different scopes. It refers to the provideRepository
which has different scope (@Singleton
) on it. If I changed the scope into ExpScope
then the CommonComponent
will have different scope with provideRepository
.
If I changed all @Singleton
into @ExpScope
then I receive this error message: depends on scoped components in a non-hierarchical scope ordering
What should I do? Or I'm doing the wrong approach here?
Use one and only one
@Singleton
scoped componentYou should have one and only one
@Singleton
scoped component like this:Only specify Activities, Fragments, and Services as explicit injection targets for Components
In an Android app, you should only list Activities, Fragments and Services as injection sites. You should configure Dagger 2 to inject the rest of your dependencies without having to resort to calling
component.inject(this)
inside them.For example, if your
CommonClass
looks like this:Refactor it like this:
Now when you have an Activity or Fragment that needs
CommonClass
and you are injecting withCommonComponent
or one of its sub-components or dependent components, they can obtain instances ofCommonClass
wired with the correct dependencies:Use subcomponents or dependent components to specify the injection targets
Now you have a
@Singleton
scoped component, you'll probably want to create a component for a narrower scope for your Activity or Fragment. You'll have to connect it to yourCommonComponent
, so use dependent components or subcomponents (subcomponents are preferred as of Dagger 2.10). Since you say you have already tried defining a@ExpScope
, I think the missing piece is to make subcomponent or dependent component with the@ExpScope
that injects your Activity or Fragment.Something like the following for the top-level singleton component:
And then for the subcomponent:
There are good working examples of Android projects in the Google Android Architecture Blueprints Github repo