2017-04-07 8 views
13

Ich fange an, Dolch 2 in einer Anwendung zu verwenden, die ich entwickle, aber ich habe einige Fragen darüber, wie Dolch 2 funktioniert.Dolch 2 Injizierende Konstruktoren

Ich bekomme die ganze Logik hinter den @Provides-Methoden und der @Inject-Annotation für die Initialisierung Ihrer Abhängigkeiten, aber die @Inject-Annotation an Klassenkonstruktoren Art von Bugs meine Meinung.

Zum Beispiel:

Im meine app, ich habe ein Modul definiert, die ContextModule, den Kontext meiner Anwendung abzurufen:

ContextModule.java

@Module 
public class ContextModule { 

    private final Context context; 

    public ContextModule(Context context) { 
     this.context = context; 
    } 

    @Provides 
    public Context context() { 
     return this.context; 
    } 
} 

Dieses Modul verwendet wird, von meiner BaseActivityComponent:

BaseActivityComponent.java

@BaseActivityScope 
@Component(modules = ContextModule.class) 
public interface BaseActivityComponent { 
    void injectBaseActivity(BaseActivity baseActivity); 
} 

So weit so gut .. dann habe ich eine AuthController-Klasse, die vom Kontext abhängt und ich möchte es in meine BaseActivity injizieren. Also in meinem AuthControllers.class Ich habe so etwas wie:

public class AuthController { 

    private Context context; 

    @Inject 
    public AuthController(Context context) { 
     this.context = context; 
    } 

    public void auth() { 
     // DO STUFF WITH CONTEXT 
    } 
} 

Und ich spritze es in meinem BaseActivity wie:

public class BaseActivity extends AppCompatActivity { 

    @Inject 
    AuthController authController; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     BaseActivityComponent component = DaggerBaseActivityComponent.builder() 
      .contextModule(new ContextModule(this)) 
      .build(); 

     component.injectBaseActivity(this); 

     authController.auth(); 

    } 
} 

Nun meine Frage ist, wie funktioniert Dolch weiß, dass mein AuthControllers eine Abhängigkeit für BasisActivity? Nur durch

@Inject 
AuthController authController; 

es ist wie die gleiche Sache zu erklären, als ob ich ein ControllerModule wie geschaffen:

@Module(includes = ContextModule.class) 
public class ControllerModule { 

    @Provides 
    AuthController authController(Context context) { 
     return new AuthController(context); 
    } 

} 

Und dann in meiner BaseActivityComponent würde ich meinen AuthController Getter hinzufügen und meine Abhängigkeit Modul ControllersModule ändern:

Wenn ich injectBaseActivity (this) aufrufen, "erzählt" Dolch, dass alle @Inject-Annotationen Abhängigkeiten von meiner Klasse sind, und dann sucht es mein Projekt ct für @Inject annotierte Konstruktoren, die diesem Typ entsprechen?

Ich dachte eine gute Sache über Dolch 2 ist, dass die Modul-Dateien als eine "Dokumentation" meiner Abhängigkeiten drei verwendet werden könnten. Aber wenn nur @Inject in allen Konstruktoren hinzugefügt wird, von denen ich die Kontrolle habe, könnte es in der Zukunft nicht ein wenig verwirrend werden, da Sie nicht wissen, was tatsächlich von was abhängt? (Ich meine, Sie wissen, was davon abhängt, Sie müssen nur eine Menge Dateien durchsuchen, um wirklich herauszufinden)

Gibt es Best Practices für die Verwendung von @Inject-Annotationen in Konstruktoren oder wenn die @Provides-Methode hinzufügen in Moduldateien? Ich bekomme das mit @Inject im Konstruktor Ich muss nicht die Konstruktordefinition in meiner Modul-Datei ändern, aber gibt es irgendwelche Nachteile?

Danke.

Antwort

23

Als ich injectBaseActivity nennen (this) it „sagt“ Dolch, der alle @Inject Anmerkungen Abhängigkeiten von meiner Klasse sind, und dann sucht es mein Projekt für @Inject Bauer kommentierte, dass diese Art passt?

Genau. Aber es ist nicht getan, wenn Sie injectBaseActivity aufrufen, aber alles geschieht während der Kompilierzeit. Dies ist eine Möglichkeit der Annotationsverarbeitung (eine andere nutzt die Reflektion zur Laufzeit).

Wenn Sie Ihr Projekt den Dolch-Annotations-Prozessor Sie umfassen (als Abhängigkeit) in Ihrer build.gradle-Datei wird mit einer Liste aller Felder, Klassen, usw. mit Anmerkungen versehen von der @Inject Annotation und baut eine Abhängigkeit bauen genannt graph damit. Anschließend wird das Diagramm aufgelöst und ein Quellcode erstellt, der alle Abhängigkeiten für die Elemente im Diagramm bereitstellt.

injectBaseActivity führt nur den Code aus, der zuvor generiert wurde, und weist alle Abhängigkeiten Ihrem Objekt zu. Es ist richtiger Quellcode, den Sie lesen und debuggen können.

Der Grund, dass dies ein Compile-Schritt ist — einfach setzen — ist Leistung und Validierung. (Z Wenn Sie einige Abhängigkeitszyklus haben, erhalten Sie einen Compiler-Fehler)


wie funktioniert Dolch weiß, dass meine AuthControllers eine Abhängigkeit für BaseActivity ist?

@Inject 
AuthController authController; 

durch das Feld @Inject Dolch mit Anmerkungen versehen kennt Sie AuthController wollen. So weit, ist es gut. Jetzt wird der Dolch nach Mitteln suchen, die den Controller bereitstellen und ihn in der Komponente, den Komponentenabhängigkeiten und den Komponentenmodulen suchen. Es wird auch geprüft, ob die Klasse eigenständig geliefert werden kann, da sie über ihren Konstruktor kennt.

Wie weiß der Dolch über den Objektkonstruktor, wenn Sie ihn nicht in ein Modul einfügen?

@Inject 
public AuthController(Context context) { /**/ } 

Durch den Konstruktor mit inject Anmerkungen versehen sagten Sie auch Dolch, dass es eine Klasse AuthController und Sie brauchen einen Kontext für sie instanziiert werden genannt wird. Es ist im Grunde das gleiche wie das Hinzufügen zu Ihrem Modul.

Ein Modul @Provides Methode sollte verwendet werden, wenn Sie nicht den Quellcode haben, nur die @Inject Annotation zum Konstruktor hinzuzufügen, oder wenn das Objekt weitere Initialisierung benötigt. Oder in Ihrem Fall ...

[...] die Moduldateien als „Dokumentation“ meine Abhängigkeiten Baum verwendet werden könnten [...]

Ja, natürlich könnte man TU das. Aber wenn Ihr Projekt wächst, müssen Sie viel von unnötigem Code pflegen, da das Gleiche mit einer einfachen Anmerkung zum Konstruktor geschehen könnte.

Gibt es Best Practices für die Verwendung von @Inject-Annotationen in Konstruktoren oder beim Hinzufügen der @Provides-Methode in Moduldateien?

Wenn Sie verschiedene Versionen für einen anderen Kontext (z.Implementieren einer Schnittstelle auf 2 verschiedene Arten) gibt es auch die @Binds Annotation, die dagger welche Klasse Sie als Implementierung bereitstellen möchten.

Ansonsten glaube ich, dass Sie immer Konstruktor Injektion verwenden sollten, wenn möglich. Wenn sich etwas ändert, müssen Sie keine anderen Teile Ihres Codes berühren, und es ist nur weniger Code, den Sie schreiben, und daher weniger Orte, an denen Sie einen Fehler einfügen könnten.

Auch Dagger kann und eine Menge nicht optimieren, indem sie mehr wissen, und wenn Sie nicht benötigten Code implementieren wird es hat mit dem Overhead arbeiten Sie

eingeführt

Natürlich am Ende ist es alles an, was Du denkst, das ist das Beste. Schließlich ist es Sie, die mit Ihre Code arbeiten muss;)

+0

Awesome Antwort. Wissen Sie, ob es möglich ist, den Kotlin-Standardkonstruktor (den mit der Klassendefinition definierten) mit inject zu kommentieren? –

+1

@saiedVanguard Es ist möglich: 'Klasse A @Inject Konstruktor (...)' –