Java Dagger 2子类具有比父类更具体的依赖项
我正在处理这样的对象层次结构:Java Dagger 2子类具有比父类更具体的依赖项,java,android,dependency-injection,dagger-2,Java,Android,Dependency Injection,Dagger 2,我正在处理这样的对象层次结构: class Foo extends View { @Inject BaseDependency dep; Foo() // Default android view constructors { injectDependencies(); } protected void injectDependencies() { getApp().getFooComponent().injec
class Foo extends View
{
@Inject BaseDependency dep;
Foo() // Default android view constructors
{
injectDependencies();
}
protected void injectDependencies()
{
getApp().getFooComponent().inject(this);
}
}
class ExtraBaseDependency extends BaseDependency
{
@Inject
ExtraBaseDependency() {}
}
class Bar extends Foo
{
@Inject ExtraBaseDependency dep;
@Override
protected void injectDependencies()
{
getApp().getBarComponent().inject(this);
}
}
我试图解决的问题是,我想在我更具体的“Bar”子类中使用更多方法的“ExtraBaseDependency”,我还想为Foo提供相同的对象,因为我正在从整个层次结构收集数据,以便在Bar中使用
我认为,通过重写injectDependencies()而不调用super,我可以为我的子类和它的父类提供它们所需的依赖项,但只有其中一个可以共享,但是Bar将获得对象更具体的接口,以便它可以完成它的工作
我看到的行为是,当它编译并运行时,我看到ExtraBaseDependency被构造了两次
My FooComponent和BarComponents具有不同的作用域和不同的模块,它们都是独立的。我不确定为什么在基类中没有得到与子类相同的实例。您的两个字段将继续存在。Foo无法访问
Bar.dep
,但Bar可以通过super.dep
访问Foo.dep
Dagger将自动注入任何类型的超类型字段和方法,
所以,如果您调用inject(Bar)
Dagger将注入Foo的字段和Bar的字段。(根据,您必须小心不要调用inject(Foo)
,因为即使在运行时传入Bar实例,也只会注入Foo的字段。)
一些解决方案:
- 随它去吧。Foo需要BaseDependency,Bar需要ExtraBaseDependency,Foo甚至可能会将该依赖项包保持私有,这样Bar就无法访问Foo的字段(如果字段是有状态的或涉及多个线程,这可能很重要)。如果你认为每个类都负责声明它自己的依赖关系,那么它是按预期的方式工作的,尽管是浪费的。
- 确定依赖项的作用域(如果应该确定其作用域)。如果BaseDependency和ExtraBaseDependency在其组件的整个生命周期内保持一致,则可以使用作用域(例如,
或@Singleton
)对其进行标记,以减少依赖项的重复,或者,如果更适合自己管理单例实例,则只需在@reusabled
@模块中保存并返回一个实例。这不是一个好的通用解决方案,但是如果这是一项长期的工作,那么您也可以用它来解决这个问题
- 如果可能的话,切换到构造函数参数(对于您的情况,它不是)。如果Bar扩展了Foo,Bar可以有一个
-注释的构造函数,该构造函数使用您请求的特定依赖项显式调用Foo的构造函数。当然,对于Android视图,您需要成员注入;这是您的其他案例或其他读者的一个选项@Inject
- 从Foo.dep中删除
注释。dep的注入显然取决于它的子类,并且字段不是多态的,因此让Foo声明它的@Inject
-注释字段对于您使用它的方式来说是不安全的@Inject
- 将Foo重构为抽象基类。这也不是所有问题的通用解决方案,但您可以通过设计用于子类化和公开BasicFoo或DefaultFoo实现的Foo来解决类层次结构问题。这将使填充Foo.dep成为子类的责任,这可能更容易在类层次结构中进行推理