Ich habe eine Weile mit dagger2 gearbeitet. Und ich war verwirrt, ob ich für jede Aktivität / jedes Fragment eine eigene Komponente / ein eigenes Modul erstellen sollte. Bitte helfen Sie mir, dies zu klären:
Zum Beispiel haben wir eine App und die App hat ungefähr 50 Bildschirme. Wir werden den Code nach dem MVP-Muster und Dagger2 für DI implementieren. Angenommen, wir haben 50 Aktivitäten und 50 Moderatoren.
Meiner Meinung nach sollten wir den Code normalerweise so organisieren:
Erstellen Sie eine AppComponent und ein AppModule, die alle Objekte bereitstellen, die verwendet werden, während die App geöffnet ist.
@Module public class AppModule { private final MyApplicationClass application; public AppModule(MyApplicationClass application) { this.application = application; } @Provides @Singleton Context provideApplicationContext() { return this.application; } //... and many other providers } @Singleton @Component( modules = { AppModule.class } ) public interface AppComponent { Context getAppContext(); Activity1Component plus(Activity1Module module); Activity2Component plus(Activity2Module module); //... plus 48 methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....) }
Erstellen Sie ActivityScope:
@Scope @Documented @Retention(value=RUNTIME) public @interface ActivityScope { }
Erstellen Sie für jede Aktivität eine Komponente und ein Modul. Normalerweise füge ich sie als statische Klassen in die Aktivitätsklasse ein:
@Module public class Activity1Module { public LoginModule() { } @Provides @ActivityScope Activity1Presenter provideActivity1Presenter(Context context, /*...some other params*/){ return new Activity1PresenterImpl(context, /*...some other params*/); } } @ActivityScope @Subcomponent( modules = { Activity1Module.class } ) public interface Activity1Component { void inject(Activity1 activity); // inject Presenter to the Activity } // .... Same with 49 remaining modules and components.
Dies sind nur sehr einfache Beispiele, um zu zeigen, wie ich dies implementieren würde.
Aber ein Freund von mir hat mir gerade eine andere Implementierung gegeben:
Erstellen Sie PresenterModule, das alle Präsentatoren bereitstellt:
@Module public class AppPresenterModule { @Provides Activity1Presenter provideActivity1Presentor(Context context, /*...some other params*/){ return new Activity1PresenterImpl(context, /*...some other params*/); } @Provides Activity2Presenter provideActivity2Presentor(Context context, /*...some other params*/){ return new Activity2PresenterImpl(context, /*...some other params*/); } //... same with 48 other presenters. }
Erstellen Sie AppModule und AppComponent:
@Module public class AppModule { private final MyApplicationClass application; public AppModule(MyApplicationClass application) { this.application = application; } @Provides @Singleton Context provideApplicationContext() { return this.application; } //... and many other provides } @Singleton @Component( modules = { AppModule.class, AppPresenterModule.class } ) public interface AppComponent { Context getAppContext(); public void inject(Activity1 activity); public void inject(Activity2 activity); //... and 48 other methods for 48 other activities. Suppose that we don't have any other Scope (like UserScope after user login, ....) }
Seine Erklärung lautet: Er muss nicht für jede Aktivität Komponenten und Module erstellen. Ich denke, die Idee meines Freundes ist überhaupt nicht gut, aber bitte korrigieren Sie mich, wenn ich falsch liege. Hier sind die Gründe:
Viele Speicherlecks :
- Die App erstellt 50 Präsentatoren, auch wenn der Benutzer nur 2 Aktivitäten geöffnet hat.
- Nachdem der Benutzer eine Aktivität geschlossen hat, bleibt sein Präsentator weiterhin bestehen
Was passiert, wenn ich zwei Instanzen einer Aktivität erstellen möchte? (Wie kann er zwei Moderatoren erstellen?)
Die Initialisierung der App dauert sehr lange (da viele Präsentatoren, Objekte usw. erstellt werden müssen).
Entschuldigung für einen langen Beitrag, aber bitte helfen Sie mir, dies für mich und meinen Freund zu klären. Ich kann ihn nicht überzeugen. Ihre Kommentare werden sehr geschätzt.
/ ------------------------------------------------- ---------------------- /
Nach einer Demo bearbeiten.
Zunächst danke für die Antwort von @pandawarrior. Ich hätte eine Demo erstellen sollen, bevor ich diese Frage gestellt habe. Ich hoffe, meine Schlussfolgerung hier könnte jemand anderem helfen.
- Was mein Freund getan hat, verursacht keine Speicherlecks, es sei denn, er legt einen Bereich für die Provides-Methoden fest. (Zum Beispiel @Singleton oder @UserScope, ...)
- Wir können viele Präsentatoren erstellen, wenn die Provides-Methode keinen Bereich hat. (Also, mein zweiter Punkt ist auch falsch)
- Dolch erstellt die Moderatoren nur dann, wenn sie benötigt werden. (Die Initialisierung der App wird also nicht lange dauern. Ich war durch Lazy Injection verwirrt.)
Alle Gründe, die ich oben gesagt habe, sind größtenteils falsch. Das heißt aber nicht, dass wir meiner Freundidee aus zwei Gründen folgen sollten:
Es ist nicht gut für die Architektur der Quelle, wenn er alle Präsentatoren in Modul / Komponente einbindet. (Es verstößt gegen das Prinzip der Schnittstellentrennung , möglicherweise auch gegen das Prinzip der Einzelverantwortung .)
Wenn wir eine Scope-Komponente erstellen, wissen wir, wann sie erstellt und wann sie zerstört wird. Dies ist ein großer Vorteil, um Speicherlecks zu vermeiden. Daher sollten wir für jede Aktivität eine Komponente mit einem @ActivityScope erstellen. Stellen wir uns bei der Implementierung meiner Freunde vor, dass wir vergessen haben, einen Bereich in die Provider-Methode aufzunehmen => Speicherlecks werden auftreten.
Meiner Meinung nach könnten wir mit einer kleinen App (nur ein paar Bildschirme ohne viele Abhängigkeiten oder mit ähnlichen Abhängigkeiten) die Idee meiner Freunde anwenden, aber das wird natürlich nicht empfohlen.
Lesen Sie lieber weiter: Was bestimmt den Lebenszyklus einer Komponente (Objektdiagramm) in Dolch 2? Dagger2 Aktivitätsumfang, wie viele Module / Komponenten benötige ich?
Und noch ein Hinweis: Wenn Sie sehen möchten, wann das Objekt zerstört wird, können Sie die Methoden zusammen aufrufen, und der GC wird sofort ausgeführt:
System.runFinalization();
System.gc();
Wenn Sie nur eine dieser Methoden verwenden, wird GC später ausgeführt, und Sie erhalten möglicherweise falsche Ergebnisse.
ControllerModule
referenzierte ein neuesPresenter
und dann wird der Präsentator in dasActivity
oder injiziertFragment
. Eine solide Meinung dafür oder dagegen?