如何覆盖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
供所有组件使用。 -
你有你的活动组件,它也知道如何构建
HelloPrinter
!
那么会发生什么呢
请记住对象图。组件知道它们可以构建什么,并依赖于其他组件,从而公开已知对象本身。
applicationComponent.provideParrot().sayHello();
这个很简单。你创建了组件,你想要一个鹦鹉,它是使用已知的打印机构建的。
activityComponent.provideParrot().sayHello();
这里发生的事情(基本上)是一样的。你说你想要一只鹦鹉。你的活动组件不知道如何制作,它只知道如何制作打印机
但是等一下它依赖于一个应用程序组件,方便地公开了一个Parrot
工厂。
调用应用程序组件工厂,并实例化鹦鹉。由于应用程序模块知道如何构建打印机,因此它使用手头的打印机。
。。。现在是什么
所以。。。你可以在你的活动组件中提供鹦鹉,然后它们会使用不同的打印机!
Gradle:错误:Parrot多次绑定
在这里,我们将把2个鹦鹉放入我们的对象图中,因为没有发生"覆盖"。这行不通,也不应该。
结论
无法覆盖方法。一旦您声明第二个Parrot
或HelloPrinter
,它将无法编译。
实现类似功能的唯一可能是在要使用的打印机上使用@Named()
注释和/或将整个鹦鹉创建下拉到活动模块中。
如果我遗漏了什么,请纠正我,但我甚至看不到使用命名注释来保持签名不变的方法。