Dagger 2子类具有比父类更具体的依赖性

时间:2017-05-09 14:21:36

标签: java android dependency-injection dagger-2

我正在处理像这样的对象层次结构:

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被构造了两次。

我的FooComponent和BarComponents具有不同的范围和不同的模块,它们是分开的。我不确定为什么我没有在基类中获得与子类相同的实例。

1 个答案:

答案 0 :(得分:2)

你的两个领域都将继续存在; fields are not polymorphic in Java。 Foo无法访问Bar.dep,但Bar可以通过Foo.dep访问super.dep

Dagger将自动注入您注入的任何类型的超类型字段和方法,  所以,如果你打电话给inject(Bar),Dagger会注入Foo的字段以及Bar的字段。 (每a note about covariance,你必须小心不要调用inject(Foo),因为即使你在运行时传入一个Bar实例,它也只会注入Foo的字段。See more here, but injecting without explicitly calling super is the right thing to do anyway.

一些解决方案:

  • 让它成为。 Foo需要BaseDependency,Bar需要ExtraBaseDependency,而Foo甚至可能将该依赖包保密 - 因此Bar无法访问Foo的字段(这可能很重要如果该字段是有状态的或者涉及多个线程)。如果您认为每个类都负责声明自己的依赖关系,那么这是按预期工作的,尽管是浪费的。

  • 如果它应该是作用域,则限制依赖项。如果BaseDependency和ExtraBaseDependency在其组件的生命周期内保持一致,则可以使用范围标记它(例如@Singleton@Reusable)减少依赖项的重新创建,或者只保存并返回@Module中的实例,如果它更适合自己管理单例实例。这不是一个好的通用解决方案,但如果这仍然是挥之不去的工作,那么你也可以用它来解决这个问题。

  • 如果可能,切换到构造函数参数(对于您的情况,不是这样)。如果Bar扩展Foo,Bar可以有一个@Inject - 带注释的构造函数,使用您请求的特定依赖项显式调用Foo的构造函数。当然,对于Android视图,你需要会员注入;这是您的其他案例或其他读者的选择。

  • 从Foo.dep中删除@Inject注释。 Foo.dep的注入显然取决于它的子类,并且字段不是多态的,所以让Foo声明它的{{1注释字段对于您使用它的方式并不安全。

  • 将Foo重构为一个抽象基类。这也不是一切的通用解决方案,但是你可以通过设计Foo来进行子类化和公开BasicFoo来清除类层次结构的困境。 DefaultFoo实现。这将使其成为填充Foo.dep的子类责任,无论如何,这可能更容易在您的类层次结构中进行推理。