2

GWT プロジェクトで GIN を使用して評価しており、コンストラクター引数を介した典型的な注入で良好な結果が得られています。私たちが苦労したのは、フィールドレベルの注入です。フィールドは常に null になります。GINでファイルレベルの注入を適切に達成する方法の良い例はありますか?

アップデート:

以下は、私たちのものに似たコードの例です。

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

}

上記のコードでは、GIN を含まないコードのほとんどを削除しました。DetailPresenter が必要とする TestPresenter は正常に注入されますが、TestPresenter が必要とする HandlerManager は常に null です。ご覧のとおり、注入された HandlerManager はコンストラクターで使用されていません。

4

1 に答える 1

1

サンプルコードを見て、更新します。

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

自分で作成しているため、インジェクションを処理したことが前提となります。このメソッドを削除すると、デフォルトのコンストラクターが呼び出され (必要に応じてそこに注入されます)、他の注入サイトにアクセスします。

発生する可能性があるもう 1 つの問題: いくつかの HandlerManager impl があるため、HandlerManager へのすべての参照で同じパッケージを使用していることを確認してください。


元の答え:

コンストラクターの実行中は null になりますが、これは理にかなっています。インジェクターがまだすべてのフィールドを割り当てる機会がない場合、他の値になる可能性があります。これがどのように実行されるかを考えてみましょう (ここでは、フィールドが公開されていない可能性があるため、法的に疑わしい Java として表現されています)。

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

フィールドが割り当てられるようになるまでに、コンストラクターは既に実行されています。

別のメソッドの実行時にフィールドが null の場合は、そのメソッドがコンストラクターによって実行されていないことを確認してください。まだ null である可能性がある他のケースは、@Inject注釈付きセッターです。

これらのケースのいずれでもないと仮定すると (チェックする最も簡単な方法は、ブレークポイントを設定し、インジェクターが呼び出しスタックにないことを確認することです)、フィールドに があり@Inject、それにバインドされていないことを確認してください。ヌル インスタンス。

于 2012-02-27T02:31:52.233 に答える