In questa domanda parlo di Dagger2. Dagger2 è costituito essenzialmente da componenti e moduli. Ecco un esempio:Legame ritardato al grafico di Dagger2 utilizzando l'elaborazione di annotazione
supponga che ho un'interfaccia:
public interface MyCoolService {
void run();
}
e una possibile implementazione:
public class MyCoolServiceImpl {
@Override
void run() {}
}
ho potuto collegare l'implementazione con l'interfaccia utilizzando Dagger2 generatrice:
@Component(modules = {MyModule.class})
@Singleton
public interface Component {
MyCoolService getMyCoolService();
}
e
@Module
public class MyModule {
@Provides @Singleton
MyCoolService provideMyCoolService() {
return new MyCoolServiceImpl();
}
}
Questa è stata una breve introduzione a Dagger2. Supponiamo ora ho la seguente interfaccia:
public interface MySecondCoolService {
void doCoolStuff();
}
non ci sono implementazioni MySecondCoolServiceImpl
di MySecondCoolService
nel codice. Invece, ho un Annotations @JustForCoolStuff
per contrassegnare campi e metodi. Ho creato un processore Annotation che raccoglie tutte queste annotazioni e genera MySecondCoolServiceImpl
che implementa MySecondCoolService
.
I il compilatore conosce la nuova interfaccia MySecondCoolService
prima che il processore di annotazione sia in esecuzione. Così ho potuto cambiare il mio Componente come:
@Component(modules = {MyModule.class})
@Singleton
public interface Component {
MyCoolService getMyCoolService();
MySecondCoolService getMySecondCoolService();
}
Il problema è che non ho un'implementazione ancora nel codice e non so il nome della realizzazione di MySecondCoolService
che viene generato da un processore di annotazione . Pertanto, non è possibile cablare l'interfaccia con l'implementazione corretta in MyModule
. Quello che posso fare è cambiare il mio processore di annotazione in modo tale da generare un nuovo modulo per me. Mio processore annotazione potrebbe generare un modulo (MyGeneratedModule
) come questo:
@Module
public class MyGeneratedModule {
@Provides @Singleton
MySecondCoolService provide MySecondCoolService() {
return new MySecondCoolServiceImpl();
}
}
Ancora MyGeneratedModule
è generato da un processore annotazione. Non ho accesso ad esso prima di eseguire il processore di annotazione anche io non conosco il nome.
Ecco il problema: Il processore di annotazione deve in qualche modo dire a Dagger2 che c'è un nuovo modulo che Dagger2 dovrebbe prendere in considerazione. Dal momento che i processori di annotazione non possono modificare i file non può estendere la @Component(modules = {MyModule.class})
annotazione e trasformarla in qualcosa di simile: @Component(modules = {MyModule.class, MyGeneratedModule.class})
C'è un modo per aggiungere MyGeneratedModule
di programmazione al grafico dagger2 dipendenze? Come può il mio Annotation Processor dire a Dagger2 che dovrebbe esserci un nuovo cablaggio tra un'interfaccia e un'implementazione come ho descritto sopra?
Foray: So che una cosa del genere può essere fatto in Google Guice e Google Gin. Un progetto che lo fa è GWTP.Ci si dispone di un presentatore:
public class StartPagePresenter extends ... {
@NameToken("start")
public interface MyProxy extends ProxyPlace<StartPagePresenter> {
}
...
}
che ha un @NameToken
un'annotazione a un'interfaccia ProxyPlace
. Nella tua AbstractPresenterModule
di cablare la vista con il presentatore e il proxy:
public class ApplicationModule extends AbstractPresenterModule {
bindPresenter(StartPagePresenter.class,
StartPagePresenter.MyView.class, StartPageView.class,
StartPagePresenter.MyProxy.class);
...
}
Come quindi si può non vedere implementazione dell'interfaccia MyProxy
è dato. L'implementazione creata da un generatore (simile al processore di annotazione ma per GWT). Ci Generator genera l'attuazione di StartPagePresenter.MyProxy
e aggiungerlo al sistema di guida/Gin:
public class StartPagePresenterMyProxyImpl extends com.gwtplatform.mvp.client.proxy.ProxyPlaceImpl<StartPagePresenter> implements buddyis.mobile.client.app.start.StartPagePresenter.MyProxy, com.gwtplatform.mvp.client.DelayedBind {
private com.gwtplatform.mvp.client.ClientGinjector ginjector;
@Override
public void delayedBind(Ginjector baseGinjector) {
ginjector = (com.gwtplatform.mvp.client.ClientGinjector)baseGinjector;
bind(ginjector.getPlaceManager(),
ginjector.getEventBus());
presenter = new CodeSplitProvider<StartPagePresenter>(ginjector.getbuddyismobileclientappstartStartPagePresenter());
...
}
}
Perché non si può solo scrivere '@Component (moduli = {MyModule.class, MyGeneratedModule.class})' nella tua codice? –
@TavianBarnes Come ho descritto nel testo non conosco il nome di '' MyGeneratedModule'' che verrà creato. –
Se si dispone di un processore di annotazione che genera una classe il cui nome non si conosce in anticipo e nessun altro modo per istanziarla, si ha un problema. Risolvi prima questo, il resto seguirà. Indipendentemente dal fatto che tu usi Dagger o meno, in realtà è irrilevante. –