Dagger 2子组件与组件依赖关系

时间:2015-04-12 07:36:25

标签: dagger dagger-2

Dagger 1的plus()方法是我在以前的应用程序中经常使用的方法,所以我理解你可能希望有一个子组件可以完全访问父图形绑定的情况。

在什么情况下使用组件依赖而不是子组件依赖是有益的?为什么?

4 个答案:

答案 0 :(得分:195)

组件依赖关系 - 当您希望保持两个组件独立时使用此选项。

子组件 - 当您想要保持两个组件耦合时使用它。

我将使用以下示例来解释组件依赖关系子组件。值得注意的一些例子是:

  • SomeClassA1可以在没有任何依赖的情况下创建。 ModuleA通过SomeClassA1方法提供了provideSomeClassA1()的实例。
  • 如果没有SomeClassB1,则无法创建
  • SomeClassA1。仅当ModuleB的实例作为SomeClassB1方法的参数传递时,SomeClassA1才能提供provideSomeClassB1()的实例。
@Module
public class ModuleA {
    @Provides
    public SomeClassA1 provideSomeClassA1() {
        return new SomeClassA1();
    }
}

@Module
public class ModuleB {
    @Provides
    public SomeClassB1 provideSomeClassB1(SomeClassA1 someClassA1) {
        return new SomeClassB1(someClassA1);
    }
}

public class SomeClassA1 {
    public SomeClassA1() {}
}

public class SomeClassB1 {
    private SomeClassA1 someClassA1;

    public SomeClassB1(SomeClassA1 someClassA1) {
        this.someClassA1 = someClassA1;
    }
}

当组件/子组件声明SomeClassA1被初始化时,Dagger将负责将provideSomeClassB1()的实例作为ModuleB方法的参数传递给ModuleB。我们需要指示Dagger如何实现依赖。这可以通过使用组件依赖子组件来完成。

组件依赖

请注意以下Component依赖示例中的以下几点:

  • ComponentB必须通过dependencies注释上的@Component方法定义依赖关系。
  • ComponentA无需声明ModuleB。这使两个组件保持独立。
public class ComponentDependency {
    @Component(modules = ModuleA.class)
    public interface ComponentA {
        SomeClassA1 someClassA1();
    }

    @Component(modules = ModuleB.class, dependencies = ComponentA.class)
    public interface ComponentB {
        SomeClassB1 someClassB1();
    }

    public static void main(String[] args) {
        ModuleA moduleA = new ModuleA();
        ComponentA componentA = DaggerComponentDependency_ComponentA.builder()
                .moduleA(moduleA)
                .build();

        ModuleB moduleB = new ModuleB();
        ComponentB componentB = DaggerComponentDependency_ComponentB.builder()
                .moduleB(moduleB)
                .componentA(componentA)
                .build();
    }
}

次要组分

请注意SubComponent示例中的以下几点:

  • 由于ComponentB尚未定义对ModuleA的依赖,因此无法独立生活。它依赖于将提供ModuleA的组件。因此它有一个@Subcomponent注释。
  • ComponentA已通过接口方法ModuleB声明componentB()。这使得两个组件耦合。实际上,ComponentB只能通过ComponentA初始化。
public class SubComponent {
    @Component(modules = ModuleA.class)
    public interface ComponentA {
        ComponentB componentB(ModuleB moduleB);
    }

    @Subcomponent(modules = ModuleB.class)
    public interface ComponentB {
        SomeClassB1 someClassB1();
    }

    public static void main(String[] args) {
        ModuleA moduleA = new ModuleA();
        ComponentA componentA = DaggerSubComponent_ComponentA.builder()
                .moduleA(moduleA)
                .build();

        ModuleB moduleB = new ModuleB();
        ComponentB componentB = componentA.componentB(moduleB);
    }
}

答案 1 :(得分:40)

根据documentation

Component Dependency只允许您通过组件依赖关系访问作为提供方法公开的绑定,即您只能访问在父Component中声明的类型。

SubComponent允许您在声明时从其父级访问整个绑定图,即您可以访问其Module中声明的所有对象。

我们假设您有一个ApplicationComponent包含所有Android个相关内容(LocationServiceResourcesSharedPreference等。您还希望将DataComponent用于管理持久性的内容以及WebService来处理API。您DataComponent中唯一缺少的是Application ContextApplicationComponent位于Context。从DataComponent获取ApplicationComponent的最简单方法是依赖Context。您需要确保在ApplicationComponent中明确声明了Submodules,因为您只能访问声明的内容。在这种情况下,没有手动工作,这意味着您不需要在父Component中指定MySubcomponent mySubcomponent = myComponent.plus(new ChildGraphModule("child!")); // No need! 并明确将子模块添加到父模块,如:

WebService

现在考虑一下您希望DataComponent LocationServiceApplicationComponent Fragment注入您@Submodule plus的情况。ApplicationComponent使用{{1}进行绑定上面的WebService功能。这里很酷的是,您绑定到(LocationService)的组件需要公开<AppenderRef ...><appender-ref ...>,因为您可以访问整个图表。

答案 2 :(得分:9)

以下是带有屏幕截图的代码示例,用于更多地了解Component和SubComponent:

组件: enter image description here

  1. AppComponent包含两个声明。
  2. AppComponent初始化为App类。
  3. HomeActivityComponent依赖于AppComponent。
  4. 在初始化DaggerHomeActivityComponent的HomeActivity中,我将AppComponent对象作为组成部分。

子组件:

enter image description here

  1. AppComponent包含一个或多个SubComponent。
  2. AppComponent初始化为App类。
  3. SubComponent不了解其ParentComponent。只能通过包含Module来提供自己的依赖性。
  4. 在HomeActivity中,我通过使用其父组件来注入SubComponent。

和图片图表enter image description here

来源:link

答案 3 :(得分:2)

到目前为止我还没有意识到的另一件事是:

  • let helper = IAPHelper() helper.completionHandler = { (val:[NSNumber] ) in print(val) } 实例只有一个父组件(尽管不同的组件可以实例化同一个@Subcomponent并且是该实例的父组件)
  • @Subcomponent可以通过component dependencies
  • 声明零个,一个或多个父组件