下方是使用 uiBinder 建立 UI 的簡單例子:
<!-- UserDashboard.ui.xml --> <ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder' xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:my='urn:import:com.my.app.widgets' > <g:HTMLPanel> <my:CricketScores ui:field='scores' /> </g:HTMLPanel> </ui:UiBinder>執行時 GWT 會偷偷的用 GWT.create() 建立 CricketScores 的實體 (經由Deferred Binding)。
但如果 CricketScores 的 Constructor 必需要傳入參數時,例如:
public CricketScores(String... teamNames) {...}這時 GWT.create() 就會出現錯誤:
[ERROR] com.my.app.widgets.CricketScores has no default (zero args) constructor. To fix this, you can define a @UiFactory method on the UiBinder's owner, or annotate a constructor of CricketScores with @UiConstructor.
這時候共有三種解決方法:
- 在 UserDashboard.java 中加入 @UiFactory method:
// method name is insignificant @UiFactory CricketScores makeCricketScores() { return new CricketScores(teamNames); }
@UiFactory method 的 method name 沒有特定的命名規則,GWT 會自動根據 return type 做判斷。也正因如此,如果一個 class 當中出現兩個相同 return type 的 @UiFactory method 時,GWT 也會顯示錯誤訊息:
[ERROR] Duplicate factory in class UserDashboard for type CricketScores
- 使用 @UiConstructor:
將 CricketScores 的 Constructor 加入 @UiConstructor annotation:
public @UiConstructor CricketScores(String teamNames) { // .... }
並在 UserDashboard.ui.xml 內,CricketScores 標籤內加入與 Constructor 參數相同的屬性即可:
<my:CricketScores ui:field='scores' teamNames='AUS, SAF, WA, QLD, VIC'/>
- 由 UiField(provided=true) 提供已建立好的物件:
於 UserDashboard's Constructor 將 CricketScores 物件傳入,並以 @UiField 宣告 reference 變數指向 CricketScores 物件:
public class UserDashboard extends Composite { interface MyUiBinder extends UiBinder<Widget, UserDashboard>; private static final MyUiBinder uiBinder = GWT.create(MyUiBinder.class); @UiField(provided=true) final CricketScores cricketScores; // cannot be private public UserDashboard(CricketScores cricketScores) { this.cricketScores = cricketScores; initWidget(uiBinder.createAndBindUi(this)); } }
沒有留言:
張貼留言