Podskładniki Dagger 2 a zależności komponentów


135

plus()Metoda Daggera 1 jest czymś, czego używałem dość często w poprzednich aplikacjach, więc rozumiem sytuacje, w których możesz chcieć mieć podkomponent z pełnym dostępem do powiązań grafów nadrzędnych.

W jakiej sytuacji byłoby korzystne użycie zależności składnika zamiast zależności podskładnika i dlaczego?

Odpowiedzi:


228

Zależności składników - użyj tej opcji, jeśli chcesz zachować niezależność dwóch składników.

Podkomponenty - użyj tej opcji, jeśli chcesz zachować połączone dwa komponenty.


Poniższy przykład posłuży do wyjaśnienia zależności składników i składników podrzędnych . W tym przykładzie warto zwrócić uwagę na:

  • SomeClassA1można tworzyć bez żadnych zależności. ModuleAzapewnia i wystąpienie za SomeClassA1pośrednictwem provideSomeClassA1()metody.
  • SomeClassB1nie można stworzyć bez SomeClassA1. ModuleBmoże dostarczyć wystąpienie SomeClassB1tylko wtedy, gdy wystąpienie SomeClassA1jest przekazane jako argument do provideSomeClassB1()metody.
@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;
    }
}

Dagger zajmie się przekazaniem instancji SomeClassA1jako argumentu do provideSomeClassB1()metody przy ModuleBkażdej ModuleBinicjalizacji deklaracji komponentu / komponentu podrzędnego . Musimy poinstruować Daggera, jak wypełnić tę zależność. Można to zrobić za pomocą zależności składnika lub składnika podrzędnego .

Zależność komponentów

Zwróć uwagę na następujące punkty w przykładzie zależności składnika poniżej:

  • ComponentBmusi zdefiniować zależność za pomocą dependenciesmetody na @Componentadnotacji.
  • ComponentAnie trzeba deklarować ModuleB. Dzięki temu oba komponenty są niezależne.
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

Zwróć uwagę na następujące punkty w przykładzie SubComponent:

  • Ponieważ ComponentBnie zdefiniował zależności od ModuleA, nie może żyć samodzielnie. Zależy to od składnika, który zapewni ModuleA. Stąd ma @Subcomponentadnotację.
  • ComponentAzadeklarował ModuleBza pomocą metody interfejsu componentB(). To sprawia, że ​​dwa komponenty są połączone. W rzeczywistości ComponentBmożna go zainicjować tylko za pośrednictwem 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);
    }
}

4
Mam konfigurację podkomponentu, która nie dodaje modułu B do komponentu A, co oznacza, że ​​konstruktor komponentuA nie potrzebuje modułu B. Wydaje się, że działa to tak, jak się spodziewałem, umożliwiając tworzenie komponentu A podczas uruchamiania aplikacji, a następnie tworzenie instancji m
FriendlyMikhail

2
@MikeN - Czy możesz podkreślić, jak możesz pozbyć się ModuleB na ComponentA? Mogę pozbyć się ModuleB na ComponentA tylko wtedy, gdy podam różne zakresy na ComponentA i ComponentB.
Praveer Gupta

1
Masz rację, moja konfiguracja działa, ponieważ mają różne zakresy. przeprosiny.
FriendlyMikhail

2
SomeClassB1zależy od SomeClassA1. ComponentAmusi jawnie zdefiniować zależność”. ==> czy miałeś na myśli " ComponentBmusi jawnie zdefiniować zależność"?
Tar

1
Podobnie do tego, co wskazał @Tar, rozumiem, że w „ SomeClassB1jest zależne od SomeClassA1. ComponentANie trzeba wyraźnie definiować zależności”. miałeś na myśli „ ComponentBnie trzeba jawnie definiować zależności”.
Sebas LG

45

Zgodnie z dokumentacją :

Component Dependencydaje ci dostęp tylko do powiązań uwidocznionych jako metody aprowizacji poprzez zależności komponentów, tj. masz dostęp tylko do typów zadeklarowanych jako nadrzędne Component.

SubComponentdaje ci dostęp do całego grafu wiązania od jego rodzica, kiedy jest zadeklarowany, tzn. masz dostęp do wszystkich obiektów zadeklarowanych w jego Modules.

Powiedzmy Powiedzmy, masz ApplicationComponentzawierający wszystkie Androidrzeczy związane ( LocationService, Resources, SharedPreference, etc). Chcesz również mieć miejsce, w DataComponentktórym zarządzasz rzeczami w celu trwałości, a także zajmujesz WebServicesię interfejsami API. Jedyne, czego ci brakuje, DataComponentto to, Application Contextco znajduje się w ApplicationComponent. Najprostszym sposobem na uzyskanie Contextfrom DataComponentbyłaby zależność od ApplicationComponent. Musisz być pewien, że masz Contextwyraźnie zadeklarowane w, ApplicationComponentponieważ masz dostęp tylko do zadeklarowanych rzeczy. W tym przypadku nie ma pracy ręcznej, co oznacza, że ​​nie musisz określać Submodulesw nadrzędnym Componenti jawnie dodawać swojego modułu podrzędnego do modułu nadrzędnego, takiego jak:

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

Teraz uważają, że przypadek, w którym chcesz, aby wprowadzić WebServiceod DataComponenti LocationServiceod ApplicationComponentdo twoich Fragmentktóry wiąże się z wykorzystaniem @Submodule plusfunkcji powyżej. Fajną rzeczą jest to, że komponent, z którym się łączysz ( ApplicationComponent) nie musi ujawniać WebServiceani LocationServicedlatego, że masz od razu dostęp do całego wykresu.


2
Jeśli dobrze rozumiem, nie ma wywoływanego interfejsu @Submodule. Czy to literówka?
Islam Salah

Podoba mi się, jak to wykorzystuje przykład z życia, aby pokazać różnicę. Jest to jednak bardziej zagmatwane niż czytanie dokumentów. Przydałoby się mniej classesprzykładów i więcej ilustracji, aby zilustrować dokładny punkt.
sudocoder

18

Oto przykład kodu ze zrzutem ekranu, aby lepiej zrozumieć składnik i składnik podrzędny:

Składnik: wprowadź opis obrazu tutaj

  1. AppComponent zawiera dwie deklaracje.
  2. AppComponent jest inicjowany w klasie App.
  3. HomeActivityComponent jest zależny od AppComponent.
  4. W HomeActivity przy inicjalizacji DaggerHomeActivityComponent daję obiekt AppComponent jako kompozycję.

Podkomponent:

wprowadź opis obrazu tutaj

  1. AppComponent zawiera SubComponent lub SubComponent.
  2. AppComponent jest inicjowany w klasie App.
  3. SubComponent nie wie o swoim ParentComponent. Zapewnia to tylko własne zależności, włączając Module.
  4. W HomeActivity wstrzykuję SubComponent za pomocą jego komponentu nadrzędnego.

I diagram obrazkowy: wprowadź opis obrazu tutaj

Źródło: link


Czy diagram nie miałby większego sensu, gdyby podskładnik obejmował AppComponent?
Florian Walther

1

Jeszcze jedna rzecz, o której do tej pory nie zdawałem sobie sprawy, to:

  • @SubcomponentInstancja ma dokładnie jeden element nadrzędny (choć różne składniki mogą instancji tego samego @Subcomponenti być rodzicem tej instancji)
  • A @Componentmoże mieć zero, jeden lub wiele komponentów „nadrzędnych” zadeklarowanych poprzez zależności komponentów

1
Prawdopodobnie w drugim przypadku nie jest poprawne stwierdzenie, że „@Component” może mieć ... rodzica (-ów). Raczej „@Component” nie ma rodziców, ale inni mogą być od tego zależni (po prostu użyj go) poprzez zależności komponentów.
zobaczcie

@demaksee Nie wiem, wydaje mi się, że jeśli odwzorujesz hierarchię komponentów, dostaniesz się do DAG i myślę, że jest to standardowy sposób określania tej relacji jako rodzic-dziecko w kontekście grafowym. Jeśli mówimy o wewnętrznym działaniu Daggera, to chyba nie jest to właściwe słowo.
arekolek
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.