razzledazzle
razzledazzle

Reputation: 6930

Is it possible to selectively set modules for components in Dagger 2?

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

Answers (1)

rdshapiro
rdshapiro

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

Related Questions