Как переопределить зависимости в пределах областей в кинжале 2

Как вы можете переопределить зависимости в разных областях кинжала 2? Пример:

У меня есть два компонента в моем приложении: ApplicationComponent и ActivityComponent . ApplicationComponent является базовым компонентом, а ActivityComponent является областью действия, где я хочу выполнить переопределение.

В этом примере я создал эти модели:

 public class Parrot { private final HelloPrinter helloPrinter; public Parrot(HelloPrinter helloPrinter) { this.helloPrinter = helloPrinter; } public void sayHello(){ helloPrinter.print(); } } public interface HelloPrinter { void print(); } public class AppHelloPrinter implements HelloPrinter{ @Override public void print() { System.out.println("Hello Application"); } } public class ActivityHelloPrinter implements HelloPrinter { @Override public void print() { System.out.println("Hello Activity"); } } 

И код:

 ApplicationComponent applicationComponent = DaggerApplicationComponent.builder().build(); applicationComponent.provideParrot().sayHello(); activityComponent = DaggerActivityComponent.builder() .applicationComponent(applicationComponent).build(); activityComponent.provideParrot().sayHello(); 

Мой желаемый результат:

 Hello Application Hello Activity 

Поэтому я создал модули:

ApplicationModule:

 @Singleton @Component(modules = ApplicationModule.class) public interface ApplicationComponent { Parrot provideParrot(); } @Module public class ApplicationModule { @Provides @Singleton HelloPrinter providePrinter(){ return new AppHelloPrinter(); } @Provides Parrot provideParrot(HelloPrinter helloPrinter) { return new Parrot(helloPrinter); } } 

ActivityModule: попытка переопределить HelloPrinter

 @PerActivity @Component(dependencies = ApplicationComponent.class, modules = ActivityModule.class) public interface ActivityComponent { Parrot provideParrot(); } @Module @PerActivity public class ActivityModule { @Provides @PerActivity HelloPrinter provideHelloPrinter() { return new ActivityHelloPrinter(); } } 

Но с этой конфигурацией вывод:

 Hello Application Hello Application 

Что я делаю неправильно? благодаря

Короткий ответ: вы не можете этого сделать.

С кинжалом все делается во время компиляции.

  1. У вас есть компонент приложения, который знает, как создать HelloPrinter и Parrot .
    Затем вы выставляете Parrot для использования всеми Компонентами.

  2. У вас есть свой компонент активности, который также знает, как построить HelloPrinter !

Так что же происходит?

Имейте в виду графический объект. Компоненты знают, что они могут создавать и зависят от других компонентов, выставляя сами известные объекты.

 applicationComponent.provideParrot().sayHello(); 

Это легко. Вы создаете компонент, вы хотите попугай, и он создан с использованием известного принтера.

 activityComponent.provideParrot().sayHello(); 

Что здесь происходит, это (в основном) то же самое. Вы говорите, что хотите попугая. Ваш компонент активности не знает, как это сделать, он просто знает, как сделать принтер!
Но ждать. Он имеет зависимость от компонента приложения, удобно Parrot фабрику Parrot .

Завод-изготовитель компонентов вызывается, и попугай получает экземпляр. Поскольку модуль приложения знает, как построить принтер, он использует один под рукой.

…что теперь

Итак … вы могли бы предоставить Parrots в своем компоненте активности, тогда они будут использовать другой принтер!

Gradle: ошибка: Parrot привязан несколько раз

Здесь мы получим 2 попугаев в наш объектный граф, так как нет «переписывания». Это не сработает, и не должно.

Вывод

Невозможно переопределить методы. Как только вы объявите второй Parrot или HelloPrinter он не HelloPrinter компиляцию.

Единственной возможностью для достижения подобной функциональности было бы использовать аннотации @Named() на которых принтер будет использовать и / или вытащить создание всего попугая в модуль активности.

И, пожалуйста, поправьте меня, если мне что-то не хватает, но я даже не вижу способа сохранить подпись так же, как использовать аннотации.