Locked History Actions

Diff for "GWT/GWTP/PlaceManager"

Differences between revisions 4 and 5
Deletions are marked like this. Additions are marked like this.
Line 66: Line 66:
この実体は、Presenter(MVPのP)オブジェクトになるのだが、このオブジェクト非常に大きくなる可能性があるため、 この実体は、Presenter(MVPのP)オブジェクトになるのだが、このオブジェクト非常に大きくなる可能性があるため、

PlaceManager

※以下は多分に想像も含まれるので注意。

モチベーション

生のGWTを使用したアプリでは、(サードパーティ製のライブラリを使わない限り)ただ一つのhtml上にすべてを描画することになる。 しかし、当然ながら「ページ」を切り替えながらユーザとの対話を行いたいアプリの作成は面倒になる。

例えばDeckLayoutPanelに複数のページウィジェットを重ねておき、見せたいものを指示するという方法がある(つまり紙芝居方式)。 ところが、この方式ではおそらく、

  • すべてのページウィジェットを最初に生成しなくてはならない。
  • ブラウザのバックボタン等に追従しない。

という問題がある。GWTPのPlaceManagerはこれを行うものであり、その機能としては

  • Proxyを使うことにより、ページの生成はオンデマンドで行われる(おそらくプロキシオブジェクトだけが最初にすべて生成される)。
  • ブラウザのバック・フォワードボタンをハンドリングして、適切なページを表示する。

というものと思われる。つまり、PlaceManagerの扱う「ページ」をPlaceと称している。

利用方法

GWTPの自動生成するサンプルコードはDIのせいで流れがわかりにくくなっているが、おおまかな流れとしては以下であると思われる。

Placeの名称を決める

各ページ(Place)の名称を決定する。サンプルコードでは、NameTokensクラスの"main"と"responce"である。

public class NameTokens {
  public static final String main = "main";
  public static final String response = "response";
....

PlaceManagerを作成する

このアプリ専用のPlaceManagerを作成する。これはClientPlaceManagerというクラスになる。 Placeへの移動要求はPlaceRequestオブジェクトで行うのだが、デフォルトのPlace用のリクエストを作成しておく。 以下のコードでは、GInjectorを使って、デフォルトPlaceの名称が注入されるようになっている。

public class ClientPlaceManager extends PlaceManagerImpl {

  private final PlaceRequest defaultPlaceRequest;

  @Inject
  public ClientPlaceManager(final EventBus eventBus,
      final TokenFormatter tokenFormatter,
      @DefaultPlace final String defaultPlaceNameToken) {
    super(eventBus, tokenFormatter);
    this.defaultPlaceRequest = new PlaceRequest(defaultPlaceNameToken);
  }

  @Override
  public void revealDefaultPlace() {
    revealPlace(defaultPlaceRequest, false);
  }
}

Placeの実装を作成する

Placeの名称とそれを管理するオブジェクトを作成したので、次にPlaceの実装を作成する。 この実体は、Presenter(MVPのP)オブジェクトになるのだが、このオブジェクトは非常に大きくなる可能性があるため、 実際には、そのプロキシを作成してPlaceの名称をつけておく。"main"については、MainPagePresenterクラスの内部クラスであるMyProxyになる。

   ...
  @ProxyStandard
  @NameToken(NameTokens.main)
  public interface MyProxy extends ProxyPlace<MainPagePresenter> {
  }
   ...

"response"についても同じ、ResponsePresenterクラスのMyProxyになる。

   ...
  @ProxyStandard
  @NameToken(NameTokens.response)
  public interface MyProxy extends ProxyPlace<ResponsePresenter> {
  }
   ...

@ProxyStandardについては詳細不明。通常はこれをつけておけばよいようだ。

DIバインディング

    bindPresenter(MainPagePresenter.class, MainPagePresenter.MyView.class,
        MainPageView.class, MainPagePresenter.MyProxy.class);