Question

Nous évaluons l'utilisation du GIN dans le projet Out GWT et avons eu de bons résultats avec l'injection typique via des arguments de constructeur. La chose avec laquelle nous avons eu des difficultés est une injection au niveau du champ. Les champs finissent toujours par être nuls. Quelqu'un a-t-il un bon exemple de la façon d'atteindre correctement l'injection de niveau déposée avec le gin?

Mise à jour:

Voici quelques exemples de code similaires aux nôtres:

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);
  }

}

Dans le code ci-dessus, j'ai supprimé la plupart du code qui n'implique pas le gin. Le TestPresenter que le détail de détail a besoin est injecté avec succès, mais le handlerManager dont le TestPresenter a besoin est toujours nul. Comme vous pouvez le voir, le handlermanager injecté n'est pas utilisé dans le constructeur.

Était-ce utile?

La solution

Mise à jour, en regardant un exemple de code:

@Provides
public TestPresenter getTestPresenter() {
  return new TestPresenter();
}

Parce que vous le créez vous-même, cela suppose que vous avez traité des injections. Supprimez cette méthode et invoquera le constructeur par défaut (y injecter si nécessaire), puis visitez tout autre site d'injection.

Un autre problème que vous pourriez rencontrer: il y a plusieurs IMPS HandlerManager, assurez-vous que toutes vos références à HandlerManager utilisent le même package.


Réponse originale:

Ils seront nuls lorsque le constructeur s'exécute, mais cela a du sens - comment pourraient-ils être une autre valeur, lorsque l'injecteur n'a pas encore eu la chance d'attribuer tous les champs. Considérez comment cela pourrait fonctionner (exprimé ici comme un java légalement légalement, car les champs peuvent ne pas être publics):

InstanceToInject instance = new InstanceToInject(...);
instance.field = provideFieldValue();

Au moment où le champ est même éligible pour être attribué, votre constructeur a déjà fonctionné.

Si le champ est nul lorsqu'une autre méthode est exécutée, assurez-vous que la méthode n'est pas exécutée par le constructeur, mais c'est après l'injection a terminé ses travaux. D'autres cas où il peut encore être nul serait @Inject sets annotés.

En supposant que ce n'est aucun de ces cas (le moyen le plus simple de vérifier est en définissant un point d'arrêt et en vous assurant que l'injecteur n'est pas dans la pile d'appels), assurez-vous que le champ a un @Inject, et qu'il n'est pas lié à une instance nul.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top