5

私の各アクティビティには、対応するシングルトン ビューの実装が必要です。それらを活動に注入するための最良の戦略は何ですか?

  1. コンストラクター注入Activity コンストラクターは、ActivityMapper の getActivity() から呼び出されます。ctor にはすでにパラメーター (Place オブジェクト) があります。考えられるすべてのビューを挿入して ActivityMapper を作成する必要があります。良くない...

  2. メソッド注入- 「そのように注釈が付けられた関数は、コンストラクターが実行された後に自動的に実行されます。」(GWT in Action、第 2 版) さて、アクティビティのstart()メソッドが呼び出されてNPE。

  3. アクティビティの ctor で GWT.create を使用してインジェクターを構築します。それらはシングルトンではなくなるため、役に立ちません。

4

3 に答える 3

7

私たちにとって最も効果的だったのは、Assisted Inject を使用することでした。

ケースに応じて、アクティビティ自体、パッケージ (そのパッケージ内のすべてのアクティビティを構築するため)、または ActivityMapper でアクティビティ ファクトリを定義しました。

public class MyActivity extends AbstractActivity {
   private final MyView view;

   @Inject
   MyActivity(MyView view, @Assisted MyPlace place) {
      this.view = view;
      ...
   }
   ...
}

public class MyActivityMapper implements ActivityMapper {
   public interface Factory {
     MyActivity my(MyPlace place);

     FooActivity foo(FooPlace place);

     ...
   }

   // using field injection here, feel free to replace by constructor injection
   @Inject
   private Factory factory;

   @Overrides
   public Activity getActivity(Place place) {
      if (place instance MyPlace) {
         return factory.my((MyPlace) place);
      } else if (place instance FooPlace) {
         return factory.foo((FooPlace) place);
      }
      ...
   }
}

// in the GinModule:
install(new GinFactoryModuleBuilder().build(MyActivityMapper.Factory.class));

ところで、メソッド インジェクションを機能させるには、GIN を使用してアクティビティを作成する必要があるため、コンストラクター インジェクションと同じ問題が発生します。魔法はありません.GINは、インスタンス化されたときに知らない、さらには知らないクラスを魔法のように注入しません。Ginjector にメソッドを追加することで明示的にメソッド インジェクションをトリガーできますが、お勧めしません (コードは Ginjector に依存するため、可能であれば避けるべきものです)。

interface MyGinjector extends Ginjector {
   // This will construct a Foo instance and inject its constructors, fields and methods
   Foo foo();

   // This will inject methods and (non-final) fields of an existing Bar instance
   void whatever(Bar bar);
}

...

Bar bar = new Bar("some", "arguments");
myGinjector.whatever(bar);
...

最後に一言: place オブジェクトをアクティビティに直接渡すつもりはありません。「シェル」レイアウトとアクティビティ マッパー。それらを本当に分離するには、何らかのナビゲーターplaceController.goTo()を作成する必要があります。これにより、呼び出しが抽象化され、アクティビティが場所を処理しないようになります。

于 2012-03-29T12:45:25.130 に答える
3

必要なすべての柔軟性を備えた、少し異なる方法を選択しました。このデザインパターンをどこで手に入れたのか覚えていませんが、私のアイデアではありませんでした. 私はそのような活動を作成します

public class MyActivity extends AbstractActivity{

    private MyView view;
    @Inject static PlaceController pc;


    @Inject
    public MyActivity(MyView view) {
        super();
        this.view = view;
    }

    public MyActivity withPlace(MyPlace myPlace) {
        return this;
    }
...
}

次に、これをアクティビティ マッパーで次のように使用します。

public class MyMapper implements ActivityMapper {

    @Inject Provider<MyActivity> myActivityProvider;

    public Activity getActivity(Place place) {

        if ( place instanceof MyPlace){
            return myActivityProvider.get().withPlace(place);
        } else if
...

また、ビューが gin モジュール ファイルでシングルトンとして宣言されていることを確認してください。

于 2012-03-29T14:36:10.400 に答える
2

私の経験では、場所とアクティビティ (マッピング) を処理する別のアクティビティ マッパーを用意することをお勧めします。プレゼンターがいるアクティビティでは、アクティビティの例を次に示します。

public class ActivityOne extends AbstractActivity {

  @Inject
  private Presenter presenter;

  @Override
  public void start(AcceptsOneWidget panel, EventBus eventBus) {
    presenter.go(panel);
  }

}

プレゼンターにはビューが内部に注入されており、「go」メソッドが呼び出されたときに構築されます(プレゼンター)。プレゼンターはGINモジュールでシングルトンとして宣言され、ビューは通常シングルトンです (多くの場所に表示される小さなウィジェットのようないくつかの例外があります)。

アイデアは、プレゼンター内のビューとの連絡先を移動することです (プレゼンターの目標は、ロジックを処理し、ビューとの間でデータを取得/更新することMVPです)。プレゼンター内にはRPCサービスもあります。宣言する必要はありません。これはGIN、呼び出しによって「魔法のように」インスタンスが作成されるためです。GWT.create 単純なプレゼンターの例を次に示します。

    public class PresenterOneImpl implements Presenter {

      @Inject
      private MyView view;


      @Inject
      private SomeRpcServiceAsync someRpc;


      @Override
      public void go(AcceptsOneWidget panel) {
        view.setPresenter(this);
        panel.setWidget(view);
        updateTheViewWithData();
      }
}

最後に、現在の状態を表示するために場所とビューを直接処理する、メニューのアクティビティなど、いくつかのアクティビティがあることに注意する必要があります。これらのアクティビティは、場所が変更されるたびに新しいインスタンスが発生しないように、マッパー内にキャッシュされます。

于 2012-03-29T13:45:13.280 に答える