IT knowledge base
CTRL+F per cercare la tua parola chiave

Dagger 2 per sviluppatori Android inesperti. Pugnale 2.Parte 2

Questo articolo è la quinta parte di una serie di articoli destinati, secondo l'autore, a coloro che non riescono a capire come gestire l' iniezione di dipendenza e il framework Dagger 2 , o semplicemente lo faranno. Originale scritto il 17 dicembre 2017. Traduzione gratis.
Immagine
Questo è il quinto articolo della serie Dagger 2 per sviluppatori Android principianti. ... Se non hai letto i precedenti, allora sei qui .

Serie di articoli

All'inizio della serie

Nell'articolo precedente, abbiamo discusso di come l'uso manuale di Dependency Injection (DI) aggiunga complessità e codice standard. Dopo aver esaminato come Dagger 2 ci allevia da questo dolore e genera codice standard per noi. Abbiamo anche esaminato i processori di annotazione e le annotazioni di base di Dagger 2. Quindi abbiamo applicato queste annotazioni tramite l'esempio e abbiamo inserito le dipendenze utilizzando Dagger 2.

Anatomia di un DaggerBattleComponent

Per una migliore comprensione di Dagger 2, considera la classeDaggerBattleComponent ... Posiziona il cursore suDaggerBattleComponent e premi Ctrl + B (o Ctrl + LMB, Comando + LMB). Vedrai quanto segue:
@Generated (
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerBattleComponent implements BattleComponent {
  private DaggerBattleComponent (Builder builder) {}

  public static Builder builder () {
    return new Builder ();
  }

  public static BattleComponent create () {
    return new Builder (). build ();
  }
  
  // implemented interface method
  @Override
  public War getWar () {
    return new War (new Starks (), new Boltons ());
  }

  public static final class Builder {
    private Builder () {}

    public BattleComponent build () {
      return new DaggerBattleComponent (this);
    }
  }
}
Questo è ciò che Dagger 2 genera per noi per risolvere il problema della dipendenza difficile . Se guardi l'interfaccia implementata dalla classe, vedrai che lo èBattleComponent  - l'interfaccia che abbiamo creato in precedenza e descritto il metodo in essagetWar() per fornire un'istanza della classeWar ...
Questa dipendenza viene fornita utilizzando il modellobuilder ... È di moda leggere di più su questo modello qui e qui .

Impariamo qualcosa di nuovo

Spero che tu capisca chiaramente perché il metodo è necessariogetWar() ... Ora voglio aggiungere un altro paio di dipendenze:Starks eBoltons ... Aggiungiamo metodi all'interfaccia:
@Component
interface BattleComponent {
    War getWar ();
    // add methods
    Starks getStarks ();
    Boltons getBoltons ();
}
Dopo aver apportato le modifiche, ricostruire il progetto. Ora controlliamo la classeDaggerBattleComponent ... Se hai fatto tutto correttamente, vedrai quanto segue.
@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class DaggerBattleComponent implements BattleComponent {
  private DaggerBattleComponent(Builder builder) {}

  public static Builder builder() {
    return new Builder();
  }

  public static BattleComponent create() {
    return new Builder().build();
  }

  @Override
  public War getWar() {
    return new War(getStarks(), getBoltons());
  }

  @Override
  public Starks getStarks() {
    return new Starks();
  }

  @Override
  public Boltons getBoltons() {
    return new Boltons();
  }

  public static final class Builder {
    private Builder() {}

    public BattleComponent build() {
      return new DaggerBattleComponent(this);
    }
  }
}
Come puoi vedere, Dagger 2 ha implementato i metodigetStarks() egetBoltons() ...
Abbiamo detto a Dagger 2 di ottenere queste dipendenze usando un'annotazione@Inject in classeBoltons ... Rompiamo qualcosa. Rimuovi annotazione@Inject dalla classeBoltons ... Ricostruisci il progetto.
Non è successo niente? Sì, non hai ricevuto alcun errore, ma prova a eseguire il progetto. Dovresti ricevere il seguente errore:
Immagine
Se leggi il testo dell'errore, allora dice chiaramente che i metodigetWar() egetBoltons() non funzionerà se non ci sono segni di annotazione@Inject o@Provides ...
Come accennato in precedenza, Dagger 2 semplifica il rilevamento dei bug. Puoi giocare un po' con questa classe.

Annotazioni@Module e@Provides

Scaviamo più a fondo e ci occupiamo di un paio di annotazioni utili -@Module e@Provides ... Vale la pena usarli se il tuo progetto sta crescendo di dimensioni.

@Module

In breve, questa annotazione contrassegna moduli e classi. Parliamo di Android. Possiamo avere un moduloContextModule e questo modulo fornirà le dipendenzeApplicationContext eContext per altre classi. Per fare ciò, dobbiamo contrassegnare la classeContextModule annotazione@Module ...

@Provides

In breve, questa annotazione è necessaria per contrassegnare i metodi che forniscono dipendenze all'interno dei moduli. Nell'esempio descritto in precedenza, abbiamo contrassegnato la classeContextModule annotazione@Module , ma dobbiamo anche contrassegnare i metodi che forniscono dipendenzeApplicationContext eContext annotazione@Provides ...
Dai un'occhiata a un piccolo esempio (link al ramo ).

Esempio

Prendiamo due servizi forniti da Braavos - Contanti e Soldati (non sono sicuro che forniscano un tale servizio, ma consideralo solo come esempio). Creiamo due classi:
public class Cash {
    public Cash () {
        // something happens
    }
}
public class Soldiers {
    public Soldiers () {
      // something happens
    }
}
Ora creiamo un modulo e gli diamo un nomeBraavosModule ... Ci fornirà due dipendenze:Cash eSoldiers ...
@Module // Module
public class BraavosModule {
    Cash cash;
    Soldiers soldiers;

    public BraavosModule (Cash cash, Soldiers soldiers) {
        this.cash = cash;
        this.soldiers = soldiers;
    }

    @Provides // Provides the Cash dependency
    Cash provideCash () {
        return cash;
    }

    @Provides // Provides the Soldiers dependency
    Soldiers provideSoldiers () {
        return soldiers;
    }
}
Come abbiamo visto in precedenza, è necessario contrassegnare tutti i moduli con un'annotazione@Module e i metodi che forniscono le dipendenze sono annotati@Provides ...
Torna in classeBattleOfBastards e dire al componente di implementare i metodiprovideCash() eprovideSoldiers() ...
@Component(modules = BraavosModule.class)
interface BattleComponent {
    War getWar();
    Cash getCash();
    Soldiers getSoldiers();
}
public class BattleOfBastards {

    public static void main (String [] args) {
        Cash cash = new Cash ();
        Soldiers soldiers = new Soldiers ();
        BattleComponent component = DaggerBattleComponent
                .builder ()
                .braavosModule (new BraavosModule (cash, soldiers))
                .build ();
        War war = component.getWar ();
        war.prepare ();
        war.report ();
        // use money and soldiers
        component.getCash ();
        component.getSoldiers ();
    }
}
Nota che il modulo è stato aggiunto alla dichiarazione di annotazione@Component ... Ciò significa che il componente conterrà questo modulo al suo interno.@Component(modules = BraavosModule.class) Dopo tutte le modifiche, ricostruisci il progetto. Vedrai un errore nel metodo.create() classeDaggerBattleComponent ... È nato dal fatto che quando si aggiunge un modulo, questa dipendenza deve essere passata a Dagger 2. Si presenta così:BattleComponent component = DaggerBattleComponent.builder().braavosModule(new BraavosModule(cash, soldiers)).build(); Dopo aver abilitato tutti i moduli, puoi iniziare a utilizzare i loro metodi tramiteComponent ...component.getCash(); component.getSoldiers(); Se vuoi essere sicuro, passa il cursore sopraDaggerBattleComponent e premi Ctrl + B (o Ctrl + LMB, Comando + LMB). Vedrai che il moduloBraavosModule incluso nella classe per fornire le dipendenzeCash eSoldiers ...

Sommario

Abbiamo analizzato le classi generate da Dagger 2 e abbiamo notato che Dagger 2 utilizza il templatebuilder per fornire dipendenze. Abbiamo anche visto un semplice esempio di utilizzo delle annotazioni@Module e@Provides ...

Qual è il prossimo?

Nel prossimo articolo, esamineremo un'applicazione Android di esempio che utilizza Dagger 2.
Il prossimo articolo uscirà il 29 dicembre o più tardi. Grazie per la vostra pazienza.