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

Dagger 2 subcomponents vs component dependencies

Dagger 1的plus()方法是我在以前的应用程序中经常使用的方法,因此我了解您可能希望拥有一个对父图绑定具有完全访问权限的子组件的情况。

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


组件依存关系-当您要使两个组件保持独立时,请使用此选项。

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

我将使用下面的示例来说明组件依赖关系和子组件。需要注意该示例的一些要点是:

  • 可以创建SomeClassA1而没有任何依赖关系。 ModuleA通过provideSomeClassA1()方法提供SomeClassA1的实例。
  • 如果没有SomeClassA1,则无法创建SomeClassB1。仅当将SomeClassA1的实例作为参数传递给provideSomeClassB1()方法时,ModuleB才能提供SomeClassB1的实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@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;
    }
}

每当初始化ModuleB的组件/子组件被初始化时,Dagger都会将SomeClassA1的实例作为参数传递给ModuleB上的provideSomeClassB1()方法。我们需要指导Dagger如何实现依赖关系。这可以通过使用组件依赖项或子组件来完成。

组件依赖性

请注意以下"组件依赖关系"示例中的以下几点:

  • ComponentB必须通过@Component批注上的dependencies方法定义依赖项。
  • ComponentA不需要声明ModuleB。这使两个组件保持独立。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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通过接口方法componentB()声明了ModuleB。这使两个组件耦合。实际上,只能通过ComponentA初始化ComponentB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
    }
}


根据文档:

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

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

假设您有一个ApplicationComponent,其中包含所有Android相关的内容(LocationServiceResourcesSharedPreference等)。您还希望在DataComponent中与WebService一起处理持久性,以处理API。 DataComponent中唯一缺少的是Application Context,它位于ApplicationComponent中。从DataComponent获取Context的最简单方法是依赖ApplicationComponent。您需要确保在ApplicationComponent中明确声明了Context,因为您只能访问声明的内容。在这种情况下,无需手动操作,这意味着您无需在父Component中指定Submodules并将子模块显式添加到父模块中,例如:

1
MySubcomponent mySubcomponent = myComponent.plus(new ChildGraphModule("child!")); // No need!

现在考虑这种情况,您想将DataComponent中的WebServiceApplicationComponent中的LocationService注入到Fragment中,并使用上述@Submodule plus功能进行绑定。这里很酷的事情是,绑定到(ApplicationComponent)的组件不需要公开WebServiceLocationService,因为您可以立即访问整个图形。


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

零件:
enter image description here

  • AppComponent包含两个声明。
  • AppComponent初始化为App类。
  • HomeActivityComponent依赖于AppComponent。
  • 在初始化DaggerHomeActivityComponent的HomeActivity中,我将AppComponent对象作为组合。
  • 子组件:

    enter image description here

  • AppComponent包含一个或多个SubComponent。
  • AppComponent初始化为App类。
  • SubComponent不了解其ParentComponent。 通过包含模块仅提供了自己的依赖性。
  • 在HomeActivity中,我通过使用其父组件来注入SubComponent。
  • 和画图:
    enter image description here

    资料来源:链接


    直到现在我还没有意识到的另一件事是:

    • @Subcomponent实例仅具有一个父组件(尽管不同的组件可以实例化相同的@Subcomponent并成为该实例的父组件)
    • @Component可能具有零个,一个或多个通过组件依赖项声明的"父"组件