Dolch 2 Unterkomponenten gegen Komponentenabhängigkeiten

135

Die plus()Methode von Dolch 1 habe ich in früheren Anwendungen häufig verwendet. Daher verstehe ich Situationen, in denen Sie möglicherweise eine Unterkomponente mit vollem Zugriff auf die übergeordneten Diagrammbindungen haben möchten.

In welcher Situation wäre es vorteilhaft, eine Komponentenabhängigkeit anstelle einer Unterkomponentenabhängigkeit zu verwenden, und warum?

Bradley Campbell
quelle

Antworten:

228

Komponentenabhängigkeiten - Verwenden Sie diese Option, wenn Sie zwei Komponenten unabhängig halten möchten.

Unterkomponenten - Verwenden Sie diese Option, wenn zwei Komponenten gekoppelt bleiben sollen.


Ich werde das folgende Beispiel verwenden, um Komponentenabhängigkeiten und Unterkomponenten zu erläutern . Einige Punkte, die es wert sind, über das Beispiel bemerkt zu werden, sind:

  • SomeClassA1kann ohne Abhängigkeit erstellt werden. ModuleAbietet und Instanz SomeClassA1über die provideSomeClassA1()Methode.
  • SomeClassB1kann nicht ohne erstellt werden SomeClassA1. ModuleBkann eine Instanz von SomeClassB1nur bereitstellen, wenn eine Instanz von SomeClassA1als Argument an die provideSomeClassB1()Methode übergeben wird.
@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 sorgt dafür, dass die Instanz von SomeClassA1als Argument an die provideSomeClassB1()Methode übergeben wird, ModuleBwenn die Deklaration der Komponente / Unterkomponente ModuleBinitialisiert wird. Wir müssen Dolch anweisen, wie die Abhängigkeit zu erfüllen ist. Dies kann entweder mithilfe der Komponentenabhängigkeit oder der Unterkomponente erfolgen .

Komponentenabhängigkeit

Beachten Sie die folgenden Punkte im folgenden Beispiel für die Komponentenabhängigkeit:

  • ComponentBmuss die Abhängigkeit über die definieren dependenciesMethode auf @ComponentAnnotation.
  • ComponentAmuss nicht deklarieren ModuleB. Dies hält die beiden Komponenten unabhängig.
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();
    }
}

Unterkomponente

Beachten Sie die folgenden Punkte im SubComponent-Beispiel:

  • Da ComponentBdie Abhängigkeit von nicht definiert wurde ModuleA, kann sie nicht unabhängig leben. Es wird abhängig von der Komponente, die das bereitstellt ModuleA. Daher hat es eine @SubcomponentAnmerkung.
  • ComponentAhat ModuleBüber die Schnittstellenmethode deklariert componentB(). Dadurch werden die beiden Komponenten gekoppelt. In der Tat ComponentBkann nur über initialisiert werden 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);
    }
}
Praveer Gupta
quelle
4
Ich habe ein Unterkomponenten-Setup, bei dem Modul B nicht zu Komponente A hinzugefügt wird. Dies bedeutet, dass der Builder für Komponente A kein Modul B benötigt. Dies scheint so zu funktionieren, wie ich es erwartet hatte, die Erstellung von ComponentA beim Start der Anwendung zuzulassen und dann m
FriendlyMikhail am
2
@MikeN - Können Sie hervorheben, wie Sie ModuleB auf ComponentA entfernen können? Ich kann ModuleB auf ComponentA nur entfernen, wenn ich auf ComponentA und ComponentB unterschiedliche Bereiche bereitstelle.
Praveer Gupta
1
Sie haben Recht, mein Setup funktioniert, weil sie sich in unterschiedlichen Bereichen befinden. Entschuldigung.
FriendlyMikhail
2
" SomeClassB1ist abhängig von SomeClassA1. ComponentAmuss die Abhängigkeit explizit definieren." ==> hast du gemeint " ComponentBmuss die Abhängigkeit explizit definieren"?
Tar
1
Ähnlich wie bei @Tar verstehe ich, dass in " SomeClassB1abhängig von SomeClassA1. Muss ComponentAdie Abhängigkeit nicht explizit definieren". Sie meinten " ComponentBmüssen die Abhängigkeit nicht explizit definieren."
Sebas LG
45

Laut Dokumentation :

Component DependencySie haben nur Zugriff auf die Bindungen, die als Bereitstellungsmethoden über Komponentenabhängigkeiten verfügbar gemacht werden, dh Sie haben nur Zugriff auf Typen, die im übergeordneten Element deklariert sind Component.

SubComponentErmöglicht Ihnen den Zugriff auf das gesamte Bindungsdiagramm von seinem übergeordneten Diagramm aus, wenn es deklariert ist, dh Sie haben Zugriff auf alle Objekte, die in seinem Modules deklariert sind .

Lassen Sie uns sagen, Sie haben ein ApplicationComponentalles enthält , was Androiddamit zu tun ( LocationService, Resources, SharedPreference, usw.). Sie möchten auch, DataComponentwo Sie Dinge für die Persistenz verwalten und WebServicemit APIs umgehen. Das einzige, was Ihnen fehlt, DataComponentist Application Contextdas, in dem Sie wohnen ApplicationComponent. Der einfachste Weg , eine zu bekommen Contextaus DataComponentwürde eine Abhängigkeit von sein ApplicationComponent. Sie müssen sicher sein, dass Sie eine Contextexplizit deklarierte haben, ApplicationComponentda Sie nur Zugriff auf deklarierte Inhalte haben. In diesem Fall gibt es keine manuelle Arbeit, dh Sie müssen nicht Submodulesim Componentübergeordneten Modul angeben und Ihr Submodul explizit einem übergeordneten Modul hinzufügen, z.

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

Betrachten Sie nun den Fall, in dem Sie WebServicevon DataComponentund LocationServicenach ApplicationComponentin Ihren injizieren möchten, Fragmentder mithilfe der @Submodule plusobigen Funktion bindet . Das Coole dabei ist, dass die Komponente, an die Sie binden ( ApplicationComponent), weder verfügbar gemacht werden muss WebServicenoch LocationServiceweil Sie sofort Zugriff auf das gesamte Diagramm haben.

Eugene
quelle
2
Wenn ich das richtig verstehe, wird keine Schnittstelle aufgerufen @Submodule. Ist es ein Tippfehler?
Islam Salah
Mir gefällt, wie dies anhand eines Beispiels aus dem wirklichen Leben den Unterschied zeigt. Dies ist jedoch verwirrender als das Lesen der Dokumente. Es wäre hilfreich, weniger classesals Beispiele und mehr Bilder zu haben, um den genauen Punkt zu veranschaulichen.
Sudocoder
17

Hier ist das Codebeispiel mit Screenshot zum besseren Verständnis von Component und SubComponent:

Komponente: Geben Sie hier die Bildbeschreibung ein

  1. AppComponent enthält zwei Deklarationen.
  2. AppComponent wird in der App-Klasse initialisiert.
  3. HomeActivityComponent ist abhängig von AppComponent.
  4. In HomeActivity zur Initialisierung von DaggerHomeActivityComponent gebe ich das AppComponent-Objekt als Komposition an.

Unterkomponente:

Geben Sie hier die Bildbeschreibung ein

  1. AppComponent enthält SubComponent oder SubComponents.
  2. AppComponent wird in der App-Klasse initialisiert.
  3. SubComponent weiß nichts über seine ParentComponent. Das liefert nur seine eigenen Abhängigkeiten, indem Modul eingeschlossen wird.
  4. In HomeActivity injiziere ich SubComponent mithilfe der übergeordneten Komponente.

Und das Bilddiagramm: Geben Sie hier die Bildbeschreibung ein

Quelle: Link

0xAliHn
quelle
Wäre das Diagramm nicht sinnvoller, wenn die Unterkomponente die AppComponent einschließen würde?
Florian Walther
1

Eine andere Sache, die ich bis jetzt nicht ganz realisiert habe, ist folgende:

  • Eine @SubcomponentInstanz hat genau eine übergeordnete Komponente (obwohl verschiedene Komponenten dieselbe instanziieren @Subcomponentund die übergeordnete Komponente dieser Instanz sein können).
  • A @Componentkann null, eine oder viele "übergeordnete" Komponenten haben, die durch Komponentenabhängigkeiten deklariert wurden
Arekolek
quelle
1
Wahrscheinlich ist es im zweiten Fall nicht richtig zu sagen, dass '@Component' möglicherweise ... Eltern hat. Vielmehr hat '@Component' keine Eltern, aber andere können über Komponentenabhängigkeiten davon abhängig sein (verwenden Sie es einfach).
Demaksee
@demaksee Ich weiß nicht, es scheint mir, dass Sie bei der Zuordnung Ihrer Komponentenhierarchie zur DAG gelangen, und ich denke, dies ist eine Standardmethode, um diese Beziehung im Diagrammkontext als Eltern-Kind zu bezeichnen. Wenn wir über das Innenleben von Dagger sprechen, dann ist es wahrscheinlich nicht das richtige Wort.
Arekolek