Multiple independent component injection

时间:2015-09-01 22:26:42

标签: java android dependency-injection dagger-2

My dagger configuration for an android project that i'm working on: Note: I've provided all the needed @Component, @Module, @Provides annotations wherever needed.

MainActivity {

@Inject A a;
@Inject B b;

 onCreate(){
    ComponentX.inject(this);
    ComponentY.inject(this);
 } 
}

ComponentX-> ModuleA ->providerA
ComponentY -> ModuleB -> providerB

As you can see, these are two completely independent components not related to each other in anyway except for at the point of injection.

During compilation I get the following error:

In file A.java
error: B cannot be provided without an @Provides- or @Produces-annotated method.
MainActivity.b
[injected field of type: B b]

Am I mistaken in thinking that multiple components can be used while using dagger 2 or is the application supposed to use one big component which takes care of all the injections?

Can anyone help me understand where i'm going wrong?

3 个答案:

答案 0 :(得分:7)

您不必拥有单个组件,有多种方法可以模块化它们,但是您创建或注入值的每个对象必须具有由单个组件提供的所有值。

重构代码的一种方法是让ComponentY依赖于ComponentX,反之亦然,例如。

@Component(dependencies = ComponentX.class)
interface ComponentY {
    void inject(MainActivity activity);
}

或者你可以创建第三个组件,比如ComponentZ,如果ComponentX和ComponentY完全相互正交。

@Component(dependencies = {ComponentX.class, ComponentY.class})
interface ComponentZ {
    void inject(MainActivity activity);
}

或者您可以重复使用这些模块,例如

@Component(modules = {ModuleA.class, ModuleB.class})
interface ComponentZ {
    void inject(MainActivity activity);
}

您决定如何拆分它在很大程度上取决于您的代码结构。如果组件X和Y是可见的但模块不是那么使用组件依赖性,因为它们(和模块依赖性)实际上是组件的实现细节。否则,如果模块可见,则可以简单地重复使用它们。

我不会使用范围,因为它们实际上是用于管理具有不同寿命的对象,例如与特定用户关联的对象,其生命周期是从用户登录到注销时的时间,或特定请求的生命周期。如果他们确实有不同的生命周期,那么您正在考虑使用范围和子组件。

答案 1 :(得分:2)

  

是应该使用一个大组件的应用程序

有点,你应该在范围内考虑它。对于给定的范围,有一个组件。范围例如是ApplicationScopeFragmentScope(保留),ActivityScopeViewScope。对于每个范围,都有一个给定的组件;组件之间不共享范围。

(这实际上意味着如果你想在@ApplicationScope中拥有全局单例,那么就有一个应用程序范围的组件。如果你想要特定于活动的类,那么你为它创建一个组件activity,取决于应用程序作用域组件。)

请参阅@MyDogTom获取@Subcomponent注释,但您也可以使用组件依赖关系来创建子范围组件。

@YScope
@Component(dependencies = ComponentX.class, modules=ModuleB.class)
public interface ComponentY extends ComponentX {
    B b();

    void inject(MainActivity mainActivity);
}

@XScope
@Component(modules=ModuleA.class)
public interface ComponentX{
    A a();
}

ComponentY componentY = DaggerComponentY.builder().componentX(componentX).build();

答案 2 :(得分:0)

  

应用程序应该使用一个需要注意的大组件   所有注射?

您可以使用Subcomponent。在您的情况下,组件声明将如下所示:

@Subcomponent(modules=ModuleB.class)
public interface ComponentY{
    void inject(MainActivity mainActivity);
}

@Component(modules=ModuleA.class)
public interface ComponentX{
    ComponentY plus(ModuleB module);
}

ComponentY创作:creationCompunentY = ComponentX.plus(new ModuleB());

现在在MainActivity,您只需拨打ComponentY.inject(this);

MainActivity {

@Inject A a;
@Inject B b;

 onCreate(){
    ComponentY.inject(this);
 } 
}

有关子组件的更多信息,请参见migration from Dagger1 guide(查看子图部分),Subcomponent JavaDocComponent JavaDoc(查看子组件部分)。