如何在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
所以我制作了模块:
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
我做错了什么?感谢
答案 0 :(得分:4)
简短的回答是......你做不到。
使用匕首,一切都在编译时完成。
您有一个应用程序组件,知道如何构建HelloPrinter
和Parrot
。
然后,为所有要使用的组件公开Parrot
。
您有自己的活动组件,也知道如何构建HelloPrinter
!
那会发生什么?
请记住对象图。组件知道它们可以构建什么并依赖于其他组件,从而暴露已知对象本身。
applicationComponent.provideParrot().sayHello();
这个很容易。你创建组件,你想要一个鹦鹉,它是使用已知的打印机构建的。
activityComponent.provideParrot().sayHello();
这里发生的事情(基本上)是相同的。你说你想要一只鹦鹉。您的活动组件不知道如何制作一个,它只知道如何制作打印机!
但等等。它依赖于应用程序组件,方便地公开Parrot
工厂。
调用应用程序组件工厂并实例化parrot。由于应用程序模块知道如何构建打印机,因此它使用了手头的那个。
...现在是什么
所以......你可以在你的活动组件中提供鹦鹉,然后他们会使用不同的打印机!
Gradle:错误:Parrot多次绑定
这里我们会得到2个鹦鹉进入我们的对象图,因为没有“覆盖”发生。这不起作用,也不应该。
<强>结论强>
无法覆盖方法。一旦声明第二个Parrot
或HelloPrinter
,它将无法编译。
实现类似功能的唯一可能性是使用@Named()
注释来使用哪个打印机和/或将整个鹦鹉创建下拉到活动模块中。
如果我遗漏了某些内容,请纠正我,但我甚至没有办法使用命名注释保持签名相同。