Dagger 2 sottocomponenti rispetto alle dipendenze dei componenti


135

Il plus()metodo di Dagger 1 è qualcosa che ho usato abbastanza spesso nelle precedenti applicazioni, quindi capisco le situazioni in cui potresti voler avere un sottocomponente con pieno accesso alle associazioni dei grafici principali.

In quale situazione sarebbe utile utilizzare una dipendenza componente anziché una dipendenza subcomponente e perché?

Risposte:


228

Dipendenze dei componenti: utilizzare questa opzione per mantenere indipendenti due componenti.

Sottocomponenti: utilizzare questa opzione per mantenere accoppiati due componenti.


Userò l'esempio seguente per spiegare le dipendenze e i sottocomponenti dei componenti . Alcuni punti da notare sull'esempio sono:

  • SomeClassA1può essere creato senza alcuna dipendenza. ModuleAfornisce e istanza di SomeClassA1tramite il provideSomeClassA1()metodo
  • SomeClassB1non può essere creato senza SomeClassA1. ModuleBpuò fornire un'istanza di SomeClassB1solo se un'istanza di SomeClassA1viene passata come argomento al provideSomeClassB1()metodo.
@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 si occuperà di passare l'istanza di SomeClassA1come argomento al provideSomeClassB1()metodo ModuleBogni volta che ModuleBviene inizializzata la dichiarazione Componente / Sottocomponente . Dobbiamo istruire Dagger su come soddisfare la dipendenza. Questo può essere fatto utilizzando la dipendenza Componente o il Sottocomponente .

Dipendenza dai componenti

Nota i seguenti punti nell'esempio di dipendenza Component di seguito:

  • ComponentBdeve definire la dipendenza tramite il dependenciesmetodo @Componentsull'annotazione.
  • ComponentAnon è necessario dichiarare ModuleB. Ciò mantiene i due componenti indipendenti.
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();
    }
}

Sottocomponente

Nota i seguenti punti nell'esempio del componente secondario:

  • Poiché ComponentBnon ha definito la dipendenza ModuleA, non può vivere in modo indipendente. Diventa dipendente dal componente che fornirà il ModuleA. Quindi ha @Subcomponentun'annotazione.
  • ComponentAha dichiarato ModuleBtramite il metodo dell'interfaccia componentB(). Questo rende i due componenti accoppiati. In effetti, ComponentBpuò essere inizializzato solo tramite 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
Ho una configurazione del sottocomponente che non aggiunge il Modulo B al Componente A, il che significa che il costruttore del componente A non ha bisogno del modulo B. Questo sembra funzionare come mi aspettavo, consentendo la creazione di ComponentA all'avvio dell'applicazione e quindi l'istanza di m
FriendlyMikhail il

2
@MikeN - Puoi evidenziare come potresti sbarazzarti di ModuleB su ComponentA? Posso eliminare ModuleB su ComponentA solo se fornisco ambiti diversi su ComponentA e ComponentB.
Praveer Gupta,

1
Hai ragione il mio setup funziona perché sono su ambiti diversi. scuse.
FriendlyMikhail,

2
" SomeClassB1dipende da SomeClassA1. ComponentADeve definire esplicitamente la dipendenza." ==> hai inteso " ComponentBdeve definire esplicitamente la dipendenza"?
Tar

1
Analogamente a quanto indicato da @Tar, capisco che in " SomeClassB1dipende da SomeClassA1. ComponentANon è necessario definire esplicitamente la dipendenza". intendevi " ComponentBnon è necessario definire esplicitamente la dipendenza".
Sebas LG,

45

Secondo la documentazione :

Component Dependencyti dà accesso solo ai binding esposti come metodi di provisioning attraverso le dipendenze dei componenti, ovvero hai accesso solo ai tipi che sono dichiarati in parent Component.

SubComponentti dà accesso all'intero grafico vincolante dal suo genitore quando è dichiarato, cioè hai un accesso a tutti gli oggetti dichiarati nei suoi messaggi Module.

Diciamo di Let, si dispone di una ApplicationComponentcontenente tutta Androidroba correlata ( LocationService, Resources, SharedPreference, ecc). Vuoi anche avere il tuo posto DataComponentdove gestire le cose per la persistenza insieme WebServicea gestire le API. L'unica cosa che ti manca DataComponentè Application Contextche risiede ApplicationComponent. Il modo più semplice per ottenere un Contextda DataComponentsarebbe una dipendenza ApplicationComponent. Devi essere sicuro di aver Contextdichiarato esplicitamente in ApplicationComponentperché hai accesso solo alle cose dichiarate. In questo caso, non c'è lavoro manuale, il che significa che non è necessario specificare Submodulesin parent Componente aggiungere esplicitamente il sottomodulo a un modulo parent come:

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

Consideriamo ora quel caso in cui si desidera iniettare WebServiceda DataComponente LocationServicedai ApplicationComponentnelle vostre Fragmentche si lega utilizzando la @Submodule plusfunzione di cui sopra. La cosa interessante qui è che il componente a cui stai vincolando ( ApplicationComponent) non ha bisogno di essere esposto WebServiceLocationServiceperché hai subito accesso all'intero grafico.


2
Se ho capito bene, non esiste un'interfaccia chiamata @Submodule. È un errore di battitura?
Islam Salah

Mi piace come questo usi un esempio di vita reale per mostrare la differenza. Tuttavia, questo è più confuso rispetto alla lettura dei documenti. Sarebbe utile avere meno classesesempi e più immagini per illustrare il punto esatto.
sudocoder

18

Ecco l'esempio di codice con screenshot per una maggiore comprensione di Componente e Sottocomponente:

Componente: inserisci qui la descrizione dell'immagine

  1. AppComponent contiene due dichiarazioni.
  2. AppComponent si inizializza nella classe App.
  3. HomeActivityComponent dipende da AppComponent.
  4. In HomeActivity all'inizializzazione di DaggerHomeActivityComponent, sto dando l'oggetto AppComponent come composizione.

Sottocomponente:

inserisci qui la descrizione dell'immagine

  1. AppComponent contiene SubComponent o SubComponents.
  2. AppComponent si inizializza nella classe App.
  3. Il componente secondario non è a conoscenza del proprio componente principale. Ciò fornisce solo le proprie dipendenze includendo il Modulo.
  4. In HomeActivity sto iniettando il sottocomponente usando il suo componente padre.

E il diagramma pittorico: inserisci qui la descrizione dell'immagine

Fonte: link


Il diagramma non avrebbe più senso se il sottocomponente racchiudesse l'AppComponent?
Florian Walther,

1

Un'altra cosa che non avevo realizzato fino ad ora è che:

  • Un @Subcomponentesempio è esattamente un componente principale (anche se i componenti differenti possono istanziare stessa @Subcomponented essere genitore che dell'istanza)
  • A @Componentpuò avere zero, uno o più componenti "parent" dichiarati attraverso le dipendenze dei componenti

1
Probabilmente nel secondo caso non è corretto affermare che '@Component' potrebbe avere ... genitori. Piuttosto '@Component' non ha genitori, ma altri potrebbero dipendere da quello (semplicemente usarlo) tramite le dipendenze dei componenti.
dal

@demaksee Non lo so, mi sembra che se mappi la tua gerarchia dei componenti, otterrai DAG, e penso che sia un modo standard di fare riferimento a questa relazione come genitore-figlio nel contesto del grafico. Se stiamo parlando del funzionamento interno di Dagger, allora suppongo che potrebbe non essere la parola giusta.
Arekolek,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.