Injeção em nível de campo GWT GIN
-
13-11-2019 - |
Pergunta
Estamos avaliando o uso de GIN em nosso projeto GWT e obtivemos bons resultados com injeção típica por meio de argumentos de construtor.O que tivemos dificuldade foi a injeção em nível de campo.Os campos sempre acabam sendo nulos.Alguém tem um bom exemplo de como obter corretamente a injeção de nível arquivado com GIN?
Atualizar:
Aqui está um exemplo de código semelhante ao nosso:
public class MVP implements EntryPoint {
public static final HandlerManager EVENT_BUS = new HandlerManager(null);
private final MVPInjector _injector = GWT.create(MVPInjector.class);
public void onModuleLoad() {
// set up layout for module
RootLayoutPanel.get().add(mainPanel);
// initialize presenters
ListPresenter listPresenter = _injector.listPresenter();
DetailPresenter detailPresenter = _injector.detailPresenter();
listPresenter.go(listContainer);
detailPresenter.go(detailContainer);
// simulate data coming in from RPC call
EVENT_BUS.fireEvent(new DataReadyEvent(getData()));
}
}
public class ListPresenter {
private final HandlerManager _eventBus;
private final Map<String, Fruit> _myRecords = new HashMap<String, Fruit>();
private final Display _view;
@Inject
public ListPresenter(Display argView, HandlerManager argEventBus) {
_eventBus = argEventBus;
_view = argView;
}
public void go(HasWidgets argContainer) {
argContainer.clear();
argContainer.add(_view.asWidget());
}
public interface Display {
public Widget asWidget();
public void clear();
public SingleSelectionModel<ViewProxy> getSelectionModel();
public void setData(List<ViewProxy> argData);
}
}
public class DetailPresenter {
private final HandlerManager _eventBus;
private final Display _view;
private Fruit _myRecord;
@Inject
private ImagePresenterFactory _imagePresenterFactory;
@Inject
private TestPresenter _testPresenter;
@Inject
public DetailPresenter(Display argView, HandlerManager argEventBus) {
_view = argView;
_eventBus = argEventBus;
}
public void go(HasWidgets argContainer) {
argContainer.clear();
argContainer.add(_view.asWidget());
if (_testPresenter != null) {
_testPresenter.go();
}
}
public interface Display {
public Widget asWidget();
public HasText getDescriptionControl();
public HasClickHandlers getImageControl();
public HasText getNameControl();
public HasClickHandlers getSaveControl();
public void setEnabledControls(boolean argEnabled);
}
}
public class TestPresenter {
@Inject
HandlerManager _eventBus;
public TestPresenter() {}
public void go() {
if (_eventBus != null) {
_eventBus.toString();
}
else {
// event bus was not injected
}
}
}
@GinModules(MVPModule.class)
public interface MVPInjector extends Ginjector {
DetailPresenter detailPresenter();
ListPresenter listPresenter();
}
public class MVPModule extends AbstractGinModule {
@Provides
@Singleton
public HandlerManager getEventBus() {
return MVP.EVENT_BUS;
}
@Provides
public TestPresenter getTestPresenter() {
return new TestPresenter();
}
@Override
protected void configure() {
bind(ListPresenter.Display.class).to(ListView.class);
bind(DetailPresenter.Display.class).to(DetailView.class);
bind(ImagePresenter.Display.class).to(ImagePopup.class);
install(new GinFactoryModuleBuilder().build(ImagePresenterFactory.class));
}
public interface ImagePresenterFactory {
public ImagePresenter createImagePresenter(ImageResource argImage);
}
}
No código acima, removi a maior parte do código que não envolve GIN.O TestPresenter exigido pelo DetailPresenter é injetado com êxito, mas o HandlerManager exigido pelo TestPresenter é sempre nulo.Como você pode ver, o HandlerManager injetado não é usado no construtor.
Solução
Atualize, observando o código de exemplo:
@Provides
public TestPresenter getTestPresenter() {
return new TestPresenter();
}
Como você mesmo está criando, presume-se que você já tenha lidado com alguma injeção.Remova este método e ele invocará o construtor padrão (injetando lá, se necessário) e, em seguida, visitará qualquer outro local de injeção.
Um outro problema que você pode estar enfrentando:existem vários impls do HandlerManager, certifique-se de que todas as suas referências ao HandlerManager usem o mesmo pacote.
Resposta original:
Eles serão nulos quando o construtor estiver em execução, mas isso faz sentido - como poderiam ser qualquer outro valor, quando o injetor ainda não teve a chance de atribuir todos os campos.Considere como isso poderia funcionar (expresso aqui como java questionavelmente legal, já que os campos podem não ser públicos):
InstanceToInject instance = new InstanceToInject(...);
instance.field = provideFieldValue();
No momento em que o campo estiver qualificado para ser atribuído, seu construtor já estará em execução.
Se o campo for nulo quando outro método for executado, certifique-se de que esse método não esteja sendo executado pelo construtor, mas é após a injeção ter terminado seu trabalho.Outros casos em que ainda pode ser nulo seriam @Inject
setters anotados.
Supondo que não seja nenhum desses casos (a maneira mais fácil de verificar é definindo um ponto de interrupção e certificando-se de que o injetor não esteja na pilha de chamadas), certifique-se de que o campo tenha um @Inject
, e que não está vinculado a uma instância nula.