Dagger - 从单独的模块中提供相同的类

时间:2014-06-28 14:33:11

标签: java dependency-injection dagger

我有一些类需要注入特定对象(让我们将其命名为ToInject)。 问题是我无法从单独的模块中提供ToInject

@Module(injects={OneActivity.class})
public class OneActivityModule {
    @Provides
    public ToInject provideToInject(){
        return new ToInject(...)
    }
}

@Module(injects={TwoActivity.class})
public class TwoActivityModule {
    @Provides
    public ToInject provideToInject(){
        return new ToInject(...)
    }
}

创建ObjectGraph时出现此异常:

Caused by: java.lang.IllegalArgumentException: TwoActivityModule: Duplicate:
    com.example.test.OneActivityModule$$ModuleAdapter$ProvideToInjectProvidesAdapter[key=com.example.test.ToInject method=com.example.test.OneActivityModule.provideToInject()]
    com.example.test.TwoActivityModule$$ModuleAdapter$ProvideToInjectProvidesAdapter[key=com.example.test.ToInject method=com.example.test.TwoActivityModule.provideToInject()]
    at dagger.ObjectGraph$DaggerObjectGraph.makeGraph(ObjectGraph.java:187)
    at dagger.ObjectGraph$DaggerObjectGraph.access$000(ObjectGraph.java:138)
    at dagger.ObjectGraph.create(ObjectGraph.java:129)

我知道我可以将ToInject个提供者移动到一个模块中,然后使用限定符来制作独特的,但为什么不能这样做呢?为每个模块指定了injects,是否也使这些提供商也独一无二?

有什么建议吗?

更新

我考虑过这个问题,真正的问题是我想根据Activity获取它来配置ToInject对象。 ToInject实际上是一个抽象类(上面的代码片段仅使用"而不是抽象"类仅用于示例)。

我的结论是我应该只为ToInject使用一个提供程序,因此我可以通过更改单行代码来更改实现。但是我仍然需要根据Activity获取它来配置ToInject对象。

所以主要问题是Dagger是否可以实现这一点,还是我必须将配置传递给每个Activity,并手动设置它?

此情况下的配置是ID(String),要配置的对象(本例中为ToInject)是显示广告横幅的片段。我想尽可能地将它与Activity分开,所以我可以在其他项目中重用它。

1 个答案:

答案 0 :(得分:0)

我找到了足够的解决方案。

这是一个负责提供摘要ToInject的实现的库。

@Module(library=true)
public class ProviderModule {
    @Provides
    public ToInject provideToInject(){
        return new ToInjectConcrete1();
    }
}

我可以通过以下方式创建特定于Activity的模块。正如您所看到的,此ToInject提供程序方法具有ToInject参数,该参数实际上是由上面的库提供的。在我得到它之后,我可以进行特定于我的Activity的进一步配置。

@Module(injects = OneActivity.class, includes = ProviderModule.class)
public class OneActivityModule {
    @Provides
    @Named("one")
    public ToInject provideToInject(ToInject toInject) {
        toInject.text = "overridden by one";

        return toInject;
    }
}

关键是使用限定符(在本例中为@Named限定符)。

注意:

我的问题的根源在于我假设提供者方法在单独的模块中(定义了injects)是唯一的。现在我知道injects用于编译时验证,并且与提供者的单一性无关。具有相同返回类型的提供者可以使用限定符(例如@Named)使其唯一,就像我在此解决方案中所做的那样。