2015-12-04 2 views
4

Caused by: java.lang.IllegalStateException: analyticsModule must be setМожно ли выборочно установить модули для компонентов в кинжале 2?

Я строю библиотеку, которая использует инициализацию в стиле шаблона. Пользователь может выборочно устанавливать модули для проекта с помощью этой библиотеки. Он использует Dagger 2 для DI.

Но Dagger 2, похоже, не позволяет использовать дополнительные модули. Невозможно просто игнорировать модули?

+0

параметризованных модулям должны быть установлены вручную, в то время как не-параметризованные модули автоматически создаются если не предоставлено через строителя. Вам, вероятно, потребуется какой-то заводский метод для предоставления «пустых модулей», если они не существуют. Но, возможно, вы можете настроить это поведение с помощью аннотации '@ Component.Builder', которая была добавлена ​​в последний моментальный снимок. – EpicPandaForce

+0

Невозможно ли пропустить полное создание модуля? Я также увижу упомянутую вами аннотацию. Использование пустых конструкторов. – razzledazzle

ответ

6

Возможно, вы захотите рассмотреть возможность использования Multibindings, который позволяет пользователям дополнительно добавлять зависимости в Set<T> или Map<K,V>. Вот пример:

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(); 
    } 
} 

В этом случае вам по-прежнему нужен экземпляр каждого модуля, даже если он не используется. Один из вариантов обойти это - использовать @Provides(type = SET_VALUES) и иметь модули, которые вы не отключили, чтобы вернуть Collections.emptySet(). Вот модифицированный пример:

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(); 
    } 
} 

Теперь вы можете позвонить:

DaggerPluginComponent.builder() 
    .moduleA(new ModuleA(Collections.emptySet()) 
    .build(); 

или в качестве альтернативы:

Set<Plugin> plugins = new HashSet<>(); 
plugins.add(new AwesomePlugin()); 
plugins.add(new BoringPlugin()); 
DaggerPluginComponent.builder() 
    .moduleA(new ModuleA(plugins) 
    .build(); 
+0

Благодарим вас за подробный ответ. Это похоже на хороший подход, но сможет ли Кинжал внедрять зависимости на основе их точных типов? – razzledazzle

+0

Не уверен, что у меня вопрос. Вы спрашиваете, работает ли это для типов без интерфейса? Можете ли вы привести пример? – rdshapiro

+0

Ну, если вы видите в 'ModuleA' или даже' ModuleB', вы можете видеть, что положения имеют тип 'Plugin', но когда я запрашиваю' FooPlugin' явно, будет ли Dagger знать, что предоставить? – razzledazzle

Смежные вопросы