Подкомпоненты Dagger 2 и зависимости компонентов

Метод кинжала 1 plus() - это то, что я использовал довольно часто в предыдущих приложениях, поэтому я понимаю ситуации, когда вы можете захотеть иметь подкомпонент с полным доступом к привязкам родительских графов.

В какой ситуации было бы полезно использовать зависимость компонента, а не зависимость от подкомпонентов и почему?

Ответ 1

Зависимости компонентов - используйте это, когда:

  • вы хотите сохранить независимые компоненты.
  • вы хотите явно указать, какие зависимости от одного компонента используются другим

Подкомпоненты - используйте это, когда:

  • вы хотите сохранить двухкомпонентную связность
  • вам может не понадобиться явно указывать, какие зависимости от одного компонента используются другим

Я попытаюсь показать это и пример. Учитывая, что мы имеем ниже модули и классы. SomeClassB1 зависит от SomeClassA1. Обратите внимание на метод provideSomeClassB1 в ModuleB, который показывает эту зависимость.

@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;
    }
}

Обратите внимание на следующие пункты в примере зависимости компонентов:

  • SomeClassB1 зависит от SomeClassA1. ComponentB должен явно определять зависимость.
  • 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:

  • SomeClassB1 зависит от SomeClassA1. ComponentB не нужно явно определять зависимость.
  • ComponentA должен объявить ModuleB. Это приводит к соединению двух компонентов.
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);
    }
}

Ответ 2

В соответствии с документация:

Component Dependency дает вам доступ только к связям, открытым в качестве методов предоставления через зависимые компоненты, т.е. вы имеете доступ только к типам, объявленным в родительском Component.

SubComponent предоставляет вам доступ ко всему графику привязки от его родителя при его объявлении, т.е. вы имеете доступ ко всем объектам, объявленным в его Module s.

Скажем, у вас есть ApplicationComponent, содержащий все связанные с Android вещи (LocationService, Resources, SharedPreference и т.д.). Вы также хотите иметь DataComponent, где вы управляете вещами для сохранения, а также WebService для работы с API. Единственное, чего вам не хватает в DataComponent, это Application Context, который находится в ApplicationComponent. Самый простой способ получить Context из DataComponent будет зависеть от ApplicationComponent. Вы должны быть уверены, что у вас есть Context, явно объявленный в ApplicationComponent, потому что у вас есть только доступ к объявленным материалам. В этом случае нет ручной работы, то есть вам не нужно указывать Submodules в родительском Component и явно добавлять ваш подмодуль к родительскому модулю, например:

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

Теперь рассмотрим тот случай, когда вы хотите вставить WebService из DataComponent и LocationService из ApplicationComponent в свой Fragment, который связывается с помощью функции @Submodule plus выше. Самое приятное, что компонент, который вы связываете с (ApplicationComponent), не должен выставлять WebService и LocationService, потому что вы сразу получаете доступ ко всему графику.

Ответ 3

Еще одна вещь, которую я до сих пор не совсем понял, заключается в следующем:

  • A @Subcomponent экземпляр имеет ровно один родительский компонент (хотя различные компоненты могут создавать экземпляр этого же @Subcomponent и быть родителем этого экземпляра)
  • A @Component может иметь ноль, один или многие родительские компоненты, объявленные через зависимые компоненты