UiBinderその2
GWTのUiBinderは単にGUIのレイアウトをXMLで記述することに留まらない素晴らしい機能がある。
AddressBookUi.xml (抜粋)
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent"> <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder" xmlns:g="urn:import:com.google.gwt.user.client.ui"> <g:HTMLPanel> <g:Grid> <g:row> <g:customCell><g:Label ui:field="lblFullName"/></g:customCell> <g:customCell><g:TextBox ui:field="txtFullName" visibleLength="20"/></g:customCell> </g:row> </g:Grid> </g:HTMLPanel> </ui:UiBinder>
ここではuiネームスペースのfield属性に注目しておいてほしい。
このようなレイアウトがあるとする。UiBinderのUi.XMLにはそれをパースしてWidgetに実体化するための、対になるクラスが必要だ。(ウィザード等でUiBinderを生成すると自動的にクラスがテンプレートとして生成される)
AddressBookUi.java
public class AddressBookUi extends Composite { private static AddressBookUiUiBinder uiBinder = GWT.create(AddressBookUiUiBinder.class); interface AddressBookUiUiBinder extends UiBinder{ } public AddressBookUi() { initWidget(uiBinder.createAndBindUi(this)); }
Ui.XMLに記述されたUiBinderのWidgetはデフォルトコンストラクタのコードに埋め込まれたAddressBookUiUiBinder#createAndBindUiメソッドにより実体化される。
ではこのコード中で実体化された"UiBinder Widget"にアクセスするにはどうしたら良いのだろう。
ここで先ほどUi.XMLの例を紹介した際のuiネームスペースのfield属性が登場する。実はこの属性で記述した名前を、クラス中のフィールド名として参照するのである。 そして参照するフィールドには@UiFieldアノテーションを記述するのだ。
AddressBookUi.java ( UiFieldアノテーション記述 )
public class AddressBookUi extends Composite { private static AddressBookUiUiBinder uiBinder = GWT .create(AddressBookUiUiBinder.class); interface AddressBookUiUiBinder extends UiBinder{ } @UiField Label lblFullName; @UiField TextBox txtFullName; : public AddressBookUi() { this.initWidget(uiBinder.createAndBindUi(this)); this.lblFullName.setText("氏名"); }
このように記述するとGWTはUi.XMLから実体化されたWidgetのインスタンスを識別して参照を@UiFieldでアノテートされたフィールドに注入する。(これが"UiBinder"と呼ばれる所以だろう。) また、これだけであればリフレクションでもなんとかなるが、GWTはコンパイル時にui.XMLとフィールド名の相互をチェックしており、合致しない場合にエラーが発生させることが出来るのである。