如何覆盖 Dagger 2 范围内的依赖项
How to override dependencies within Scopes in Dagger 2
如何覆盖 Dagger 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
所以我制作了模块:
应用模块:
@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
我做错了什么?谢谢
简短的回答是......你不能那样做。
使用 dagger 一切都在编译时完成。
您有一个应用程序组件,它知道如何构建 HelloPrinter
和 Parrot
。
然后公开 Parrot
供所有组件使用。
你有你的 activity 组件,它也知道如何构建 HelloPrinter
!
那会发生什么?
记住对象图。组件知道它们可以构建什么并依赖于其他组件,从而公开已知对象。
applicationComponent.provideParrot().sayHello();
这个很简单。您创建了组件,您想要一只鹦鹉,它是使用已知打印机构建的。
activityComponent.provideParrot().sayHello();
这里发生的事情(基本上)是一样的。你说你想要一只鹦鹉。您的 activity 组件不知道如何制造一个,它只知道如何制造一台打印机!
等等。它依赖于一个应用程序组件,方便地公开一个Parrot
工厂。
调用应用程序组件工厂并实例化鹦鹉。由于应用程序模块 知道 如何构建打印机,因此它使用手边的打印机。
...现在怎么样
所以...您可以在 activity 组件中提供 Parrots,然后它们将使用不同的打印机!
Gradle: error: Parrot is bound multiple times
这里我们将 2 只鹦鹉放入我们的对象图中,因为没有 "overwriting" 发生。这行不通,也不应该。
结论
无法覆盖 方法。一旦你声明第二个 Parrot
或 HelloPrinter
它将编译失败。
实现类似功能的唯一可能性是在要使用的打印机上使用 @Named()
注释和/或将整个鹦鹉创建拉入 activity 模块。
如果我遗漏了什么请纠正我,但我什至没有看到使用命名注释保持签名相同的方法。
如何覆盖 Dagger 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
所以我制作了模块:
应用模块:
@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
我做错了什么?谢谢
简短的回答是......你不能那样做。
使用 dagger 一切都在编译时完成。
您有一个应用程序组件,它知道如何构建
HelloPrinter
和Parrot
。
然后公开Parrot
供所有组件使用。你有你的 activity 组件,它也知道如何构建
HelloPrinter
!
那会发生什么?
记住对象图。组件知道它们可以构建什么并依赖于其他组件,从而公开已知对象。
applicationComponent.provideParrot().sayHello();
这个很简单。您创建了组件,您想要一只鹦鹉,它是使用已知打印机构建的。
activityComponent.provideParrot().sayHello();
这里发生的事情(基本上)是一样的。你说你想要一只鹦鹉。您的 activity 组件不知道如何制造一个,它只知道如何制造一台打印机!
等等。它依赖于一个应用程序组件,方便地公开一个Parrot
工厂。
调用应用程序组件工厂并实例化鹦鹉。由于应用程序模块 知道 如何构建打印机,因此它使用手边的打印机。
...现在怎么样
所以...您可以在 activity 组件中提供 Parrots,然后它们将使用不同的打印机!
Gradle: error: Parrot is bound multiple times
这里我们将 2 只鹦鹉放入我们的对象图中,因为没有 "overwriting" 发生。这行不通,也不应该。
结论
无法覆盖 方法。一旦你声明第二个 Parrot
或 HelloPrinter
它将编译失败。
实现类似功能的唯一可能性是在要使用的打印机上使用 @Named()
注释和/或将整个鹦鹉创建拉入 activity 模块。
如果我遗漏了什么请纠正我,但我什至没有看到使用命名注释保持签名相同的方法。