I'm still new to Dagger and trying to get a hang of things. I wanted to split my modules into logical groups which each provide their own functionality, yet basically would act the same as if it were in one Module.
For instance, let's say I have my main application module defined as follows:
//com.example.android.MyAppModule.java
@Module(
includes = AnalyticsModule.class,
injects = { <snip> }
)
public class MyAppModule {
// various provides
}
And I have another module defined like this which sets up an ErrorReporter interface and provides the concrete implementation to it.
// com.example.android.analytics.AnalyticsModule.java
@Module(
addsTo = MyAppModule.class,
injects = { MyApp.class }
)
public class AnalyticsModule(){
// ErrorReporter is a public interface and ErrorReporterImpl is a package-local final concrete class that implements it
@Provides @Singleton
ErrorReporter providesErrorReporter(ErrorReporterImpl reporter) { return reporter };
}
In my Application class I set up the object graph like this:
// com.example.android.MyApp.java
public class MyApp extends Application {
@Inject ErrorReporter errorReporter;
@Override
public void onCreate() {
super.onCreate();
applicationGraph = ObjectGraph
.create(new MyAppModule())
.plus(new AnalyticsModule());
applicationGraph.inject(this);
errorReporter.initialize();
}
}
When I run the dagger compiler I get something like this:
Graph validation failed: Module Inclusion Cycle:
0. com.example.android.analytics.AnalyticsModule included by com.example.android.MyAppModule
1. com.example.android.modules.MyAppModule included by com.example.android.analytics.AnalyticsModule
0. com.example.android.analytics.AnalyticsModule
What am I doing wrong here? I assume it has something to do with includes/addsTo, but when I remove those I get other errors.
If I remove includes = AnalyticsModule.class from MyAppModule I get something like this:
com.example.android.analytics.ErrorReporter could not be bound with key com.example.android.analytics.ErrorReporter required by com.example.android.MyApp for com.example.android.MyAppModule
Everything is fine if I completely forgo an AnalyticsModule and then hand off the providesErrorReporter to MyAppModule, but then I have to make my concrete impl class public so I can use it in the other module.
@Module(includes = AnalyticsModule.class)
is useful for composing multiple modules into one module. In this case, using .plus(new AnalyticsModule())
is wrong because AnalyticsModule
has already been included by the includes
line in the annotation. So you should remove the call to plus()
.
@Module(addsTo = MyAppModule.class)
is for allowing a call to .plus(new AnalyticsModule())
. Since we've removed that call, we should remove the addsTo
as well.
@Module(complete = false)
is necessary for AnalyticsModule
because some of its dependencies can't be satisfied on its own. This is okay; as long as MyAppModule
has complete = true
(the default), Dagger will do the necessary error checking.
Admittedly, the "Module Inclusion Cycle" error was a little bit unclear. The cycle was caused by A including B which addsTo A.
addsTo=
is there to specify that this graph is an extension to the referenced module in a parent/child graph. .plus() is the run-time version of this. You only need .plus() if you have shorter-lived graph-managed instances. This corresponds roughly to the notion of "scope" in Guice and other DI containers.
In your example you are doing:
applicationGraph = ObjectGraph
.create(new MyAppModule())
.plus(new AnalyticsModule());
This ends up creating two graphs in a parent/child relationship, which isn't what you need here. IN an android app you want one graph for the Application.
You can simply remove addsTo and MyAppModule will automatically instantiate AnalyticsModule, or you can pass both in if you want to avoid the dynamic initialization like so:
applicationGraph = ObjectGraph.create(new MyAppModule(), new AnalyticsModule());
The module inclusion cycle is because you have a cyclical relationship between these two modules and modules must themselves form an acyclic graph of configuration. MyAppModule includes AnalyticsModule which in turn includes MyAppModule. (addsTo is a less rigorous includes= used to specify things obtained from parent graphs)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With