Reputation: 6930
Caused by: java.lang.IllegalStateException: analyticsModule must be set
I'm building a library that uses template-style initialization. The user can selectively setup modules for the project with that library. It uses Dagger 2 for DI.
But Dagger 2 doesn't seem to allow optional modules. Can't unset modules be simply ignored?
Upvotes: 7
Views: 2528
Reputation: 766
You might want to consider using Multibindings, which allows for users to optionally add in dependencies into a Set<T>
or Map<K,V>
. Here's an example:
interface Plugin {
void install(Application application);
}
@Component({ModuleA.class, ModuleB.class})
interface PluginComponent {
Set<Plugin> plugins();
}
@Module
class ModuleA {
@Provides(type = SET) Plugin providFooPlugin() {
return new FooPlugin();
}
}
@Module
class ModuleB {
@Provides(type = SET) Plugin providBarPlugin() {
return new BarPlugin();
}
}
In this case, you still need an instance of each module, even if it's not used. One option to get around this would be to use @Provides(type = SET_VALUES)
, and have modules that you wan't turned off to return Collections.emptySet()
. Here's a modified example:
interface Plugin {
void install(Application application);
}
@Component({ModuleA.class, ModuleB.class})
interface PluginComponent {
Set<Plugin> plugins();
}
@Module
class ModuleA {
private final Set<Plugin> plugins;
ModuleA(Set<Plugin> plugins) {
this.plugins = plugins;
}
@Provides(type = SET_VALUES) Plugin providFooPlugins() {
return plugins;
}
}
@Module
class ModuleB {
@Provides(type = SET) Plugin providBarPlugin() {
return new BarPlugin();
}
}
Now, you can call:
DaggerPluginComponent.builder()
.moduleA(new ModuleA(Collections.emptySet())
.build();
Or alternatively:
Set<Plugin> plugins = new HashSet<>();
plugins.add(new AwesomePlugin());
plugins.add(new BoringPlugin());
DaggerPluginComponent.builder()
.moduleA(new ModuleA(plugins)
.build();
Upvotes: 6