Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

Locked History Actions

GWT/GWTP/PlaceManager

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については詳細不明。通常はこれをつけておけばよいようだ。

ワイヤリングを行う

gwtpでは標準でGINを使用しているので、このワイヤリングを行う。

ClientModule.java

....
public class ClientModule extends AbstractPresenterModule {

  @Override
  protected void configure() {
    install(new DefaultModule(ClientPlaceManager.class));

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

    bindConstant().annotatedWith(DefaultPlace.class).to(NameTokens.main);

    bindPresenter(ResponsePresenter.class, ResponsePresenter.MyView.class,
        ResponseView.class, ResponsePresenter.MyProxy.class);
  }
}

ClientGinjector.java

...
@GinModules({ DispatchAsyncModule.class, ClientModule.class })
public interface ClientGinjector extends Ginjector {

  EventBus getEventBus();

  PlaceManager getPlaceManager();

  Provider<MainPagePresenter> getMainPagePresenter();

  Provider<ResponsePresenter> getResponsePresenter();
}