[JAVA] Lesen Sie die offizielle Dagger2-Dokumentation, um die Grundlagen zu verstehen

Auslösen

Dagger2 wird auch im Android-Entwicklerhandbuch zur App-Architektur (https://developer.android.com/topic/libraries/architecture/guide.html) vorgestellt. Es ist an der Zeit ** Ich denke, es ist unwahrscheinlich, dass Android-Ingenieure Dagger2 oder DI nicht verstehen **, also habe ich es nachgeschlagen. Wenn Sie sich nicht sicher sind, lesen Sie bitte das entsprechende [Ergänzende Memo]. Da der Quellcode veröffentlicht wird, kann es leicht vorstellbar sein. Diesmal konnte ich die kürzlich aktualisierte Beziehung zu Android (dagger.android) nicht ansprechen. Mutig, was dich als Dolchanfänger überrascht hat.

Es ist fast eine Übersetzung der folgenden Dokumente. Bitte weisen Sie darauf hin, was falsch ist.

User's Guide https://google.github.io/dagger/users-guide.html

User's Guide

Dolch2 Übersicht

Als gute Klasse für viele Apps wird BarcodeDecoder wahrscheinlich Klassenabhängigkeiten wie BarcodeCameraFinder, DefaultPhysicsEngine und HttpStreamer aufweisen. Im Gegensatz dazu ist ein Beispiel für eine schlechte Klasse eine Klasse, die Speicherplatz beansprucht, ohne etwas zu tun, wie z. B. BarcodeDecoderFactory. Sie können dies durch das Entwurfsmuster für die Abhängigkeitsinjektion ersetzen. Das Testen kann durch Zusammenstellen mit Standardanmerkungen von javax.inject (JSR 330) vereinfacht werden. Es ist keine Implementierung erforderlich, die sie durch eine Klasse ersetzt, um die Web-API von Fake zu erreichen. ** Die Abhängigkeitsinjektion dient nicht nur zum Testen. Sie können Module erstellen, die einfach wiederverwendet und ersetzt werden können. ** Beispielsweise kann das Authentifizierungsmodul freigegeben und in der App verwendet werden, oder das DevLoggingModule kann zum Debuggen verwendet werden und das ProdLoggingModule kann in der Produktion verwendet werden.

Warum unterscheidet sich Dagger2 von anderen DIs?

Bisher gab es viele DI-Bibliotheken. Warum haben Sie die Räder neu entwickelt? Dagger2 ist der erste, der vollständig durch Codegenerierung implementiert wird. Die Richtlinie besteht darin, eine Abhängigkeitsinjektion zu generieren, die so einfach, nachvollziehbar und ausführbar wie möglich ist.

Abhängigkeitserklärung

Dolch Erstellt eine Instanz der Klasse der Anwendung und füllt ihre Abhängigkeiten. Verwenden Sie javax.inject.Inject annotation, um Konstruktoren und Felder zu identifizieren. Verwenden Sie einen Konstruktor, der die Annotation "@ Inject" verwendet, wenn Dagger eine Klasse instanziiert. Wenn eine neue Instanz benötigt wird, erhält Dagger die erforderlichen Parameter und ruft den Konstruktor auf.

class Thermosiphon implements Pump {
  private final Heater heater;

  @Inject
  Thermosiphon(Heater heater) {
    this.heater = heater;
  }

  ...
}

Dolch kann auch Felder (Mitgliedsvariablen) direkt einfügen. In diesem Beispiel wird eine Instanz des Heizfelds und des Pumpenfelds eingefügt.

class CoffeeMaker {
  @Inject Heater heater;
  @Inject Pump pump;

  ...
}

Wenn es ein Feld mit ** @ Inject und keinen Konstruktor mit @ Inject gibt, erstellt Dagger das Feld auf Anfrage, versucht jedoch nicht, die Instanz zu erstellen. (Wahrscheinlich wie diese Kaffeemaschine.) Wenn Sie mit @ Inject einen Konstruktor ohne Argumente erstellen, wird auf die gleiche Weise eine Instanz erstellt. ** ** ** Dolch unterstützt auch die Methodeninjektion, wird jedoch häufig in Feldern und Konstruktoren verwendet. Klassen ohne "@ Inject" können nicht mit Dagger erstellt werden.

[Ergänzender Hinweis] Abhängigkeitserklärung

Es war ein Stück Code, also ist es schwer zu verstehen, nicht wahr?

Das ist das Bild. (Der Code ist hier. Https://github.com/takahirom/dagger2-sample/commit/4b4e7a047dee0993735c6605bc06bdcd3084c8b8) Der Bereich um @ Component werde ich später vorstellen, aber eine Component erstellen und den Maker () aufrufen. ** Wenn Sie maker () aufrufen, wird nur eine neue Instanz von CoffeeMaker () und eine neue Instanz von Heater () in dieses CoffeeMaker-Feld zurückgegeben. ** ** **

Ich mache eine Komponente (später beschrieben)

public class MainActivity extends AppCompatActivity {

    private CoffeeShop coffeeShop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coffeeShop = DaggerMainActivity_CoffeeShop.create();
        System.out.println(coffeeShop.maker());
    }

    @Component
    interface CoffeeShop {
        CoffeeMaker maker();
    }
}

Mit "@ Inject" kann der Konstruktor von Dagger ausgeführt werden, und mit "@ Inejct" wird auch das Feld angegeben.

class CoffeeMaker {
    @Inject
    Heater heater;

    @Inject
    public CoffeeMaker() {
    }
}

Aus dem Feld wird auch eine Heizung erstellt.

class Heater {
    @Inject
    public Heater() {
    }
}

Diesmal habe ich "@ Inject" für das Feld (Mitgliedsvariable) verwendet. Wenn Sie es an das Argument des Konstruktors anhängen, wird zuerst das Objekt des Arguments neu erstellt und der Konstruktor, der es verwendet, aufgerufen.

Abhängigkeiten erfüllen

Standardmäßig füllt Dolch die Abhängigkeit, indem er den angeforderten Typ erstellt. Wenn Sie CoffeeMaker anfordern, legt new CoffeeMaker () die Felder fest, die injiziert werden können. "@ Inject" kann jedoch nicht überall verwendet werden.

In solchen Fällen kann eine Methode, die "@ Provides" verwendet, die Abhängigkeit erfüllen. Der Rückgabewert der Methode sollte ein Typ sein, der die Abhängigkeit erfüllt.

Beispielsweise wird die Methode requireHeader aufgerufen, wenn Heater benötigt wird.

@Provides static Heater provideHeater() {
  return new ElectricHeater();
}

** Auch Methoden mit @ Provides können ihre eigenen Abhängigkeiten haben. Hier ist ein Beispiel für die Rückgabe eines Thermosiphons, wenn eine Pumpe benötigt wird. ** ** **

@Provides static Pump providePump(Thermosiphon pump) {
  return pump;
}

Methoden mit @ Provide müssen zu einem Modul gehören. Fügen Sie der Klasse einfach die Annotation @ Module hinzu.

@Module
class DripCoffeeModule {
  @Provides static Heater provideHeater() {
    return new ElectricHeater();
  }

  @Provides static Pump providePump(Thermosiphon pump) {
    return pump;
  }
}

** Konventionell sollte die Methode "@ Provides" einen Methodennamen haben, der mit "begin" beginnt, und das Modul sollte einen Klassennamen haben, der mit "Module" endet. ** ** **

[Ergänzender Hinweis] Erfüllen Sie die Abhängigkeit

Ich werde es in Richtung des Aufbaus der folgenden Beziehung zusammenfassen (Grafik).

Bauen Sie eine Beziehung auf (Grafik)

Klassen mit "@ Injection" und "@ Provides" bilden Beziehungen, die durch Abhängigkeiten erstellt wurden. Greifen Sie über einen "Satz gut definierter Zuordnungsrouten" mit einem aufrufenden Code wie der main () -Methode der Anwendung oder der Android-Anwendungsklasse auf die Zuordnung (Grafik) zu. In Dagger2 wird die Menge in einer Schnittstelle deklariert, in der ** die gewünschte Klasse eine Methode ohne Rückgabeargument hat. ** Wenden Sie die Annotation "@ Component" an und übergeben Sie das Modul an die Module der Annotation, um mit diesem Modul eine vollständige Implementierung zu erstellen.

@Component(modules = DripCoffeeModule.class)
interface CoffeeShop {
  CoffeeMaker maker();
}

Es wird eine Klasse für den Dolch und die erste Komponente generiert, aus der Sie eine Instanz von CoffeeShop erstellen können.

CoffeeShop coffeeShop = DaggerCoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())
    .build();

Wenn es sich um eine innere Klasse handelt, wird sie mit einem solchen Trennzeichen _ generiert

In den folgenden Fällen wird es DaggerFoo_Bar_BazComponent genannt.

class Foo {
  static class Bar {
    @Component
    interface BazComponent {}
  }
}

Dieses dripCoffeeModule () wird nicht benötigt, wenn die DripCoffeeModule-Klasse Zugriff auf den Standardkonstruktor hat (und dies nicht sein muss). Wenn alle Methoden mit "@ Provides" statisch sind, muss der Konstruktor nicht zugänglich sein.

DaggerCoffeeShop.builder()
    .dripCoffeeModule(new DripCoffeeModule())

Wenn Sie keine Instanz des Moduls benötigen, können Sie die Methode create () wie folgt verwenden, anstatt den Builder zu verwenden.

CoffeeShop coffeeShop = DaggerCoffeeShop.create();

Jetzt können Sie CoffeeShop einfach mit einer Implementierung verwenden, die es Dagger ermöglicht, eine vollständig abhängige Kaffeemaschine zu erhalten.

public class CoffeeApp {
  public static void main(String[] args) {
    CoffeeShop coffeeShop = DaggerCoffeeShop.create();
    coffeeShop.maker().brew();
  }
}

[Ergänzender Hinweis] Erfüllen Sie die Abhängigkeit

Diesmal war es auch ein Fragment des Codes, daher ist es möglicherweise schwer zu verstehen, daher werde ich den gesamten Code einfügen. (Hier ist der Code. Https://github.com/takahirom/dagger2-sample/commit/7adcffb7b4b38d1aede06645df9bbdc37603bd23)

public class MainActivity extends AppCompatActivity {

    private CoffeeShop coffeeShop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coffeeShop = DaggerMainActivity_CoffeeShop.create();
        System.out.println(coffeeShop.maker());
    }

    @Component(modules = DripCoffeeModule.class)
    interface CoffeeShop {
        CoffeeMaker maker();
    }

    @Module
    static class DripCoffeeModule {
        @Provides static Heater provideHeater() {
            return new ElectricHeater();
        }

        @Provides static Pump providePump(Thermosiphon pump) {
            return pump;
        }
    }

}
class CoffeeMaker {
    @Inject
    Heater heater;
    @Inject
    Pump pump;

    @Inject
    public CoffeeMaker() {
    }
}

Derzeit gibt es leere @ Inject-only-Klassen wie Heater, Pump, ElectricHeater und Thermosiphon.

public class ElectricHeater extends Heater {
    @Inject
    public ElectricHeater(){

    }
}

Mit "@ Module" können Sie sehen, dass jede Instanz verwendet wird. image.png

Grafikbindung

Dieses Beispiel zeigt ein Beispiel für das Erstellen einer Komponente unter Verwendung typischer Bindungen. Es gibt jedoch verschiedene Mechanismen, die bei der Assoziationsbindung (Grafikbindung) helfen. Folgendes kann beim Erstellen von Abhängigkeiten verwendet werden, um Komponenten in gutem Zustand zu erstellen.

(Es scheint folgendes zu geben, aber ich verstehe nicht alles)

Singleton- und Scoped-Bindungen

@ Singleton ist an eine Methode mit @ Provides oder einer injizierbaren Klasse angehängt. Grafik Verwenden Sie eine Instanz für alle Benutzer.

@Provides @Singleton static Heater provideHeater() {
  return new ElectricHeater();
}

@ Singleton für die Klasse ist auch als Dokument nützlich. Sie können sehen, dass diese Klasse von mehreren Threads gemeinsam genutzt werden kann.

@Singleton
class CoffeeMaker {
  ...
}

** Dagger2 verbindet Instanzen mit Gültigkeitsbereich (einschließlich "@ Singleton") in Graph mit Instanzen der Implementierung der Komponente **, sodass Sie den Umfang der Komponente festlegen müssen. Zum Beispiel ist es nicht sinnvoll, dass dieselbe Komponente gleichzeitig eine @ @ Singleton-Bindung (was anscheinend eine Bindung an ein Objekt im Diagramm bedeutet) und eine @ RequestScoped-Bindung (benutzerdefinierter Bereich) hat. Weil es sich in einer Komponente mit einem anderen Lebenszyklus befinden muss. Um einen benutzerdefinierten Bereich zu erstellen, wenden Sie einfach die Anmerkungen auf die Komponente an.

@Component(modules = DripCoffeeModule.class)
@Singleton
interface CoffeeShop {
  CoffeeMaker maker();
}

[Ergänzende Anmerkung] Singleton- und Scoped-Bindungen

Wie werden Singleton-Instanzen verwaltet? (Hier ist der Code https://github.com/takahirom/dagger2-sample/commit/063b7f45c9fb97e54b90ce56a4f96b217e39a6bc )

Dagger2 verbindet Instanzen mit Gültigkeitsbereich (einschließlich "@ Singleton") in Graph mit Instanzen der Implementierung der Komponente. Was bedeutet das? Wie wird es gehandhabt?

Als einfaches Beispiel habe ich mit @ Singleton experimentiert.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final CoffeeShop coffeeShop =  DaggerMainActivity_CoffeeShop.create();
        System.out.println(coffeeShop.maker());
        System.out.println(coffeeShop.maker());
        final CoffeeShop coffeeShop2 = DaggerMainActivity_CoffeeShop.create();
        System.out.println(coffeeShop2.maker());
        System.out.println(coffeeShop2.maker());

    }

    @Singleton
    @Component(modules = DripCoffeeModule.class)
    interface CoffeeShop {
        CoffeeMaker maker();
    }

    
}
@Singleton
class CoffeeMaker {
    @Inject
    Heater heater;
    @Inject
    Pump pump;

    @Inject
    public CoffeeMaker() {
        System.out.println("new CoffeeMaker()");
    }
}

Dies gibt Folgendes aus: Mit anderen Worten, @ Singleton scheint mit Coffee Shop verbunden zu sein.

new CoffeeMaker()
com.github.takahirom.dagger_simple.CoffeeMaker@a69a8a4
com.github.takahirom.dagger_simple.CoffeeMaker@a69a8a4
new CoffeeMaker()
com.github.takahirom.dagger_simple.CoffeeMaker@336f60d
com.github.takahirom.dagger_simple.CoffeeMaker@336f60d

Ich habe versucht, den Speicher in diesem Zustand zu sichern. In dieser Implementierung verschwindet der Verweis auf CoffeeMaker, dh die Instanz verschwindet, wenn MainActivity.onCreate () endet.

image.png

Was ist, wenn ich eine Instanz von CoffeeShop in Actviity habe?

public class MainActivity extends AppCompatActivity {

    private CoffeeShop coffeeShop;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        coffeeShop = DaggerMainActivity_CoffeeShop.create();
        System.out.println(coffeeShop.maker());
        System.out.println(coffeeShop.maker());
    }

Es scheint, dass die Instanz vom CoffeeMakerProvider im Feld der DaggerMainActivity_CoffeeShop-Klasse gehalten wird, die automatisch von Dagger generiert wird und die Schnittstelle von CoffeeShop implementiert.

image.png

** Dagger2 machte irgendwie Sinn, ** Instanzen mit Gültigkeitsbereich (einschließlich @ Singleton) in Graph mit Instanzen der Implementierung der Komponente zu verbinden. Ich habe auch ohne @Singleton experimentiert, aber die CoffeeMaker-Instanz ist normal verschwunden.

Wiederverwendbarer Bereich

Manchmal möchten Sie die Anzahl der Instanziierungen begrenzen, manchmal müssen Sie sie jedoch nicht auf eine beschränken. Die Instanziierung ist beispielsweise unter Android ein teurer Prozess. In solchen Fällen können Sie "@ Reusable" verwenden. @ Reusable bindet im Gegensatz zu anderen Bereichen nicht an eine Komponente. Stattdessen gibt die Komponente eine zwischengespeicherte Instanz zurück oder instanziiert sie. ... (Es scheint eine Funktion zu sein, die nicht oft verwendet wird, daher werde ich sie diesmal weglassen **)

Freisetzbare Referenzen

... (Es scheint so implementiert zu sein, aber es scheint, dass es nicht viel verwendet wird, also ** werde ich es diesmal weglassen **)

@Inject @ForReleasableReferences(MyScope.class)
ReleasableReferences myScopeReferences;

void lowMemory() {
  myScopeReferences.releaseStrongReferences();
}

...

Lazy injections Manchmal kann es notwendig sein, die Instanziierung zu verzögern. Sie können die Instanziierung verzögern, bis Sie die get () -Methode von Lazy für eine Bindung T aufrufen. Wenn T eine einzelne Tonne ist, ist alles in ObjectGraph dieselbe Instanz. Wenn es sich nicht um einen Singleton handelt, wird er an jedem Injektionspunkt instanziiert. Ab dem zweiten Mal wird jedoch dieselbe Instanz zurückgegeben.

class GridingCoffeeMaker {
  @Inject Lazy<Grinder> lazyGrinder;

  public void brew() {
    while (needsGrinding()) {
      // Grinder created once on first call to .get() and cached.
      lazyGrinder.get().grind();
    }
  }
}

Provider injections Möglicherweise benötigen Sie mehrere Instanzen, anstatt einen einzelnen Wert einzufügen. Es gibt verschiedene Optionen, z. B. Factory oder Builder. Eine Option ist jedoch die Verwendung von Provider anstelle eines T-Typs. Der Anbieter ruft die Bindungslogik bei jedem Aufruf der get () -Methode auf. Wenn die Bindungslogik ein Konstruktor mit @Inject ist, wird eine neue Instanz erstellt. Es gibt jedoch keine solche Garantie, wenn die Instanz mit einer Methode mit "@ Provides" erstellt wird.

class BigCoffeeMaker {
  @Inject Provider<Filter> filterProvider;

  public void brew(int numberOfPots) {
  ...
    for (int p = 0; p < numberOfPots; p++) {
      maker.addFilter(filterProvider.get()); //new filter every time.
      maker.addCoffee(...);
      maker.percolate();
      ...
    }
  }
}

Hinweis: Code, der Provider einfügt, kann verwirrenden Code erzeugen, der dazu führen kann, dass im Diagramm falsch kopierte Objekte, falsch kopierte oder falsch strukturierte Objekte verwendet werden. In vielen Fällen können Sie Fabriken, Lazy , verwenden oder die Lebensdauer und Struktur Ihres Codes neu konfigurieren, um T zu injizieren. In einigen Fällen kann Provider effizient implementiert werden. Eine häufige Verwendung ist, wenn Sie eine Legacy-Architektur nutzen müssen, die nicht zur natürlichen Lebensdauer des Objekts passt.

(** Wird auch in der Beispiel-App für Architekturkomponenten verwendet ** https://github.com/googlesamples/android-architecture-components/blob/e33782ba54ebe87f7e21e03542230695bc893818/GithubBrowserSample/app/src/main/java/com/android/ Beispiel / github / viewmodel / GithubViewModelFactory.java # L30)

Qualifiers Manchmal reichen Typen allein nicht aus, um Abhängigkeiten zu identifizieren. Zum Beispiel möchte ich in einer hoch entwickelten Kaffeemaschine die Heizung für Wasser und die Heizung für die Kochplatte trennen. Fügen Sie in diesem Fall eine Qualifikationsanmerkung hinzu. Dies ist eine Anmerkung mit @ Qualifier. Die Deklaration von "@ Named" der in javax.inject enthaltenen Qualifier-Annotation lautet wie folgt.

@Qualifier
@Documented
@Retention(RUNTIME)
public @interface Named {
  String value() default "";
}

Sie können Ihre eigene Qualifikationsanmerkung erstellen oder @Named verwenden. Sie kann durch Anwenden von Anmerkungen auf Felder oder Argumente eingeschränkt werden. Typen und Qualifikationsanmerkungen werden verwendet, um Abhängigkeiten zu identifizieren.

class ExpensiveCoffeeMaker {
  @Inject @Named("water") Heater waterHeater;
  @Inject @Named("hot plate") Heater hotPlateHeater;
  ...
}

Stellt den durch Annotieren der entsprechenden @ Provides-Methode angegebenen Wert bereit.

@Provides @Named("hot plate") static Heater provideHotPlateHeater() {
  return new ElectricHeater(70);
}

@Provides @Named("water") static Heater provideWaterHeater() {
  return new ElectricHeater(93);
}

Abhängigkeiten dürfen nicht mehrere Qualifikationsmerkmalanmerkungen enthalten. (?)

[Ergänzungsnotiz] Qualifikanten

Ich habe es tatsächlich versucht und versucht zu sehen, was passieren würde, wenn ich einen anderen Namen in named eingeben würde. (Hier ist der Code https://github.com/takahirom/dagger2-sample/commit/fbabf72a454ec7a96628783a81e12bcb765d6cad)

    @Module
    static class DripCoffeeModule {
        @Provides
        @Named("water")
        static Heater provideHeater() {
            return new ElectricHeater();
        }
class CoffeeMaker {
    @Inject
    @Named("hot plate")
    Heater heater;
...
}

Es erkennt es als Fehler richtig und scheint mich beim Kompilieren richtig zu warnen.

MainActivity.java:30:Error: @javax.inject.Named("hot plate") com.github.takahirom.dagger_simple.Heater cannot be provided without an @Provides- or @Produces-annotated method.
        CoffeeMaker maker();
                    ^
      @javax.inject.Named("hot plate") com.github.takahirom.dagger_simple.Heater is injected at
          com.github.takahirom.dagger_simple.CoffeeMaker.heater
      com.github.takahirom.dagger_simple.CoffeeMaker is provided at
          com.github.takahirom.dagger_simple.MainActivity.CoffeeShop.maker()
1 Fehler

Sie können es kompilieren, wenn Sie es wie unten gezeigt richtig wässern.

class CoffeeMaker {
    @Inject
    @Named("water")
    Heater heater;

Optional bindings ... (Es scheint eine Funktion zu sein, wenn Optional und Dagger von Java 8 oder Guava verwendet werden, daher werde ich sie weglassen.)

Binding Instances Beim Bauen von Bauteilen sind häufig Daten verfügbar. Stellen Sie sich beispielsweise eine Anwendung vor, die Befehlszeilenargumente verwendet. Möglicherweise möchten Sie diese Argumente innerhalb einer Komponente binden. Angenommen, Ihre Anwendung verwendet ein Argument (String), das den Namen des Benutzers darstellt, den Sie mit der Anmerkung "@ UserName" einfügen möchten. Sie können dem Component Builder "@ BindsInstance" hinzufügen, damit Sie diese Instanz in den Component Builder einfügen können.

@Component(modules = AppModule.class)
interface AppComponent {
  App app();

  @Component.Builder
  interface Builder {
    @BindsInstance Builder userName(@UserName String userName);
    AppComponent build();
  }
}

Und die App sieht so aus.

public static void main(String[] args) {
  if (args.length > 1) { exit(1); }
  App app = DaggerAppComponent
      .builder()
      .userName(args[0])
      .build()
      .app();
  app.run();
}

Wenn Sie im obigen Beispiel den String "@ UserName" in eine Komponente einfügen, wird beim Aufrufen dieser Methode die dem Builder bereitgestellte Instanz verwendet. (? Ich wusste nicht, wo sich diese Methode befindet ...) Sie müssen alle @ BindsInstance-Methoden aufrufen, bevor Sie die Komponente erstellen. Die folgenden "@ Nullable" -Bindungen sind eine Ausnahme. Wenn der Parameter der Methode "@ BindsInstance" mit "@ Nullable" markiert ist, wird die Bindung auf die gleiche Weise wie die Methode "@ Provides" als "nullable" betrachtet. Daher ist der Injektor auch "@ Nullable" und Null muss akzeptiert werden. Sie können auch den Builder-Methodenaufruf weglassen, bei dem die Komponente die Instanz als null behandelt. ** Die Methode "@ BindsInstance" sollte bevorzugt verwendet werden, anstatt sie an "@ Module" im Konstruktor zu übergeben und sofort anzupassen. ** ** **

(Dies ist auch ein Beispiel für Architekturkomponenten https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/di/AppComponent. Java # L38 scheint verwendet zu werden.)

[Ergänzende Anmerkung] Bindungsinstanzen

Es ist fast das gleiche, aber schauen wir uns den Code an (der Code ist hier https://github.com/takahirom/dagger2-sample/commit/c2cbfdbbf883203378ad51fd1d629ea25a7dbe6f)

Das Qualifikationsmerkmal scheint gut für das zu sein, das im Beispiel Benutzername war. Also benutze ich es bei @Named. Dieses Mal habe ich versucht zu überlegen, ob ich Zucker verwenden soll, wenn ich die Anwendung starte.

Ich habe angegeben, Zucker mit Zucker zu verwenden (wahr) (ich werde Zucker hinzufügen)

        coffeeShop = DaggerMainActivity_CoffeeShop.builder().sugar(true).build();
        System.out.println(coffeeShop.maker());

Es ist das gleiche wie im Beispiel.

    @Singleton
    @Component(modules = DripCoffeeModule.class)
    interface CoffeeShop {
        CoffeeMaker maker();

        @Component.Builder
        interface Builder {
            @BindsInstance
            Builder sugar(@Named("sugar") boolean isAddingSugger);
            CoffeeShop build();
        }
    }

Setzen Sie den Zucker ein, wo Sie es wollen.

class CoffeeMaker {
...
    @Inject
    @Named("sugar")
    boolean isAddSugar;

Validierung zur Kompilierungszeit

... (Dagger's Annotation Processor ist streng und gibt einen Fehler aus, wenn er falsch ist, also werde ich ihn weglassen.)

Codegenerierung zur Kompilierungszeit

Der Annotation-Prozessor von Dagger generiert automatisch Klassen wie CoffeeMaker_Factory.java und CoffeeMaker_MembersInjector.java. Diese Klassen sind die Details der Implementierung von Dagger. Es ist nützlich beim Debuggen durch Injektionen, aber Sie müssen sie nicht direkt nutzen. ** Alles, was Sie in Ihrem Code benötigen, ist einer, der mit Dagger für die Komponente beginnt. ** ** **

Wie man Dolch im Build benutzt

... (Ich werde es weglassen, weil es doch Android ist.)

Zusammenfassung

Ich hatte das Gefühl, dass es bequem wäre, wenn ich es meistern könnte. Wenn Sie mit Dagger eine Instanz einer bestimmten Klasse erstellen, handelt es sich dann um eine Kette zum Erstellen von Instanzen, z. B. zum Erstellen von Argumenten für dieses Feld oder diese Methode? Es war sehr praktisch, weil ich es tun würde. Zunächst habe ich jedoch das Gefühl, dass die Lernkosten etwas hoch sind, und ich hoffe, dass es Menschen gibt, die mit dieser Qiita etwas einfacher werden.

Recommended Posts

Lesen Sie die offizielle Dagger2-Dokumentation, um die Grundlagen zu verstehen
[java8] Um die Stream-API zu verstehen
Verstehen Sie die Grundlagen von Android Audio Record
Java-Referenz zum Verständnis in der Abbildung
[Ruby] Von den Grundlagen bis zur Injektionsmethode
Warum war das Lesen des Codes schmerzhaft?
[Ruby-Grundlagen] Verwendung der Slice-Methode
[Für Anfänger] Verstehen Sie schnell die Grundlagen von Java 8 Lambda
Verstehen Sie die Eigenschaften von Scala in 5 Minuten (Einführung in Scala)
In der Abbildung verstandene Java-Klassen und -Instanzen