2017-04-21 10 views
1

Ich bin ziemlich neu in Dolch 2 und ich suche nach einer Möglichkeit, eine "konfigurierbare Komponente" zu haben.Dolch 2 Modul "Schnittstellen"?

Im Wesentlichen ist es das, was ich erreichen will:

public interface ErrorReporter{ 
    ... 
} 

public class ConsoleErrorReporter implements ErrorReporter{ 
    ... // Print to System.err 
} 

public class DialogErrorReporter implements ErrorReporter{ 
    ... // Show modal dialog to user 
} 


@Module 
public interface UIModule{ 
    @Provides 
    ErrorReporter provideErrorReporter(); 
} 

@Module 
public class ConsoleUIModule{ 
    @Override 
    @Provides 
    ErrorReporter provideErrorReporter(ConsoleErrorReporter cer){ 
     return cer; 
    } 
} 


@Module 
public class GraphicalUIModule{ 
    @Override 
    @Provides 
    ErrorReporter provideErrorReporter(DialogErrorReporter der){ 
     return der; 
    } 
} 

@Component(modules = {UIModule.class, OtherUniversalModule.class}) 
public interface ApplicationComponent{ 
    ErrorReporter errorReporter(); 
} 


void main(String[] args){ 
    final UIModule uiModule; 
    if(args.length == 1 && args[0].equals("gui")){ 
     uiModule = new GraphicalUIModule(); 
    }else{ 
     uiModule = new ConsoleUIModule(); 
    } 

    DaggerApplicationComponentdac = DaggerApplicationComponent.builder() 
             .uiModule(uiModule).build(); 
    dac.errorReporter().showError("Hello world!"); 
} 

Die oben mit @Provides methods cannot be abstract leider sowohl für Schnittstellen und abstrakte Klassen ausfällt. Ich habe auch nicht abstrakte Basisklasse mit konkreten Implementierungen versucht, die null zurückgeben und dann diese in Unterklassen überschreiben. Dies schlägt jedoch auch mit @Provides methods may not override another method fehl.

Kurz gesagt, ich möchte einen Vertrag für ein Modul definieren und während der Laufzeit verschiedene Module auswählen. Ich weiß, dass die Dagger 2 Kompilierzeit den Objektgraphen validiert, aber wenn ich einen gut definierten Vertrag habe, sollte das noch möglich sein, oder? Oder muss ich zwei verschiedene Komponenten mit doppeltem Code für beide Benutzeroberflächen erstellen? Gibt es andere Lösungen, die ich vermisse?

Antwort

2

Ich glaube nicht, ein Modul auf diese Weise möglich ist, weil ...

Sie die folgenden zwei Konstrukteurs

für Ihre Klassen haben Angenommen
@Inject ConsoleErrorReporter(Console console); 

@Inject DialogErrorReporter(Graphics graphics); 

Dies würde bedeuten, dass ConsoleUIModule ein erfordern würde Console und DialogErrorReporter würden ein Graphics Objekt benötigen, um ihre jeweilige Implementierung von ErrorReporter zu erstellen.

Aber wenn Dolch nur über UIModule weiß, weil Sie die Schnittstelle dort verwenden ... gut ... es konnte die Abhängigkeiten für beide nicht zur Verfügung stellen, weil es nichts von ihnen kennt.

Und wenn Sie nicht wissen, die Abhängigkeiten erstellen ein Abhängigkeitsdiagramm zur Kompilierzeit wird nicht funktionieren. Auch das wird auch ohne Dolch nicht kompiliert, da provideErrorReporter(ConsoleErrorReporter cer)provideErrorReporter() nicht überschreibt.


Was Sie tun können und sollten, ist die Verwendung verschiedener Komponenten. Weil eine Komponente das Ding ist, das wirklich weiß, wie man Dinge bereitstellt. Und eine Komponente ist bereits eine Schnittstelle — und das ist, was Sie wollten, oder?

Sie können Komponentenabhängigkeiten haben, wobei eine Komponente von einer anderen abhängt. Z.B. Haben Sie eine DependentComponent, die eine NeedsErrorReporter bereitstellt, die eine Implementierung von ErrorReporter benötigt. Wir sind auch abhängig von einer Schnittstelle, anstatt der eigentlichen Komponente (und das war, was Sie schließlich wollten, oder?)

Sie implementieren dann die Schnittstelle von tatsächlichen Komponenten, und jede Komponente hat ihre jeweiligen Module (und vielleicht noch weitere Abhängigkeiten)). Am Ende haben Sie eine Komponente, die Sie wechseln können und bietet verschiedene Versionen eines Objekts, ordnungsgemäß gekapselt!

@Component(dependencies = UIComponent.class) /* <- an interface! */ 
interface DependentComponent { 
    NeedsErrorReporter needsErrorReporter(); 
} 

class NeedsErrorReporter { 
    @Inject public NeedsErrorReporter(ErrorReporter reporter) { } 
} 


/* this is _not_ a component, but a simple interface! */ 
interface UIComponent { 
    ErrorReporter errorReporter(); 
} 


/* Console */ 
@Component(modules = ConsoleUIModule.class) 
interface ConsoleUIComponent extends UIComponent { } 

@Module interface ConsoleUIModule { 
    @Binds ErrorReporter provideErrorReporter(ConsoleErrorReporter cer); 
} 

/* Graphic */ 
@Component(modules = GraphicalUIModule.class) 
interface GraphicUIComponent extends UIComponent { } 

@Module interface GraphicalUIModule { 
    @Binds ErrorReporter provideErrorReporter(DialogErrorReporter der); 
} 

/* The error reporter variants */ 
interface ErrorReporter { 
} 

class ConsoleErrorReporter implements ErrorReporter { 
    @Inject public ConsoleErrorReporter() { } 
} 

class DialogErrorReporter implements ErrorReporter { 
    @Inject public DialogErrorReporter() { } 
} 

Alles was Sie jetzt tun müssen, ist die richtige Komponente holen;)

DaggerDependentComponent.builder().uIComponent(DaggerConsoleUIComponent.create()).build(); 
    // or 
DaggerDependentComponent.builder().uIComponent(DaggerGraphicUIComponent.create()).build(); 
+0

ich irgendwie habe es funktioniert, wenn ich mit 'javac' durch' kompilieren gradle' es kompiliert ... aber Ich bekomme Fehler, wenn ich in Eclipse mit 'm2apt' kompiliere (oder w/e heißt es), aus irgendeinem Grund erzeugt es nicht die Dolch-Komponente für eine der Komponenten, die die" Interface-Komponente "erbt ... Haben Sie dies festgestellt ? –

+0

@EmilyL.Ich habe noch nie Eclipse mit Annotationsprozessoren benutzt, also weiß ich es ehrlich gesagt nicht. Vielleicht verwendest du eine andere Dolch-Version mit Eclipse? Ich habe '2.10' benutzt. –

+0

Ich verwende das 'apt'-Plugin in Gradle, um die Eclipse-Dateien zu generieren. Und ich habe nachgeprüft, dass es der gleiche Dagger '2.10' ist. Ich werde tiefer graben müssen: –