IAm*_*aja 7 java gwt widget uibinder gwt-designer
我正在学习GWT并尝试围绕所有UI选项.我正在尝试了解何时/何地/如何使用Widgets,UIBinder,GWT Designer和自定义小部件.特别:
com.google.gwt.user.client.ui.*与com.google.gwt.user.client.ui.Composite?之间的区别是什么?对我而言,我觉得所有这些事情都做同样的事情,也许这只是GWT为您提供多种方式来完成演示的方式?如果没有,请在这些项目上纠正我.
当窗口小部件非常简单时,我只在UiBinder上使用窗口小部件.例如,我只是添加了两个小部件Panel.如果涉及任何CSS,我总是使用UiBinder,因为使用样式更容易.
小部件不会被翻译成UiBinder XML.所有GWT代码都成为添加和操作DOM元素的JavaScript,因此所有内容都被转换为可执行语言,而不是模板系统.
我写了很多UiBinder片段.我尝试遵循您可以在网络上找到的有关抽象和构图的良好规则.
如果您有任何非平凡的逻辑,MVP模式是必须的,因为使用JUnit测试无GWT的演示者非常快速和简单,而GWT测试具有更多的开销并且速度慢得多.
我喜欢在CSS文件中保留尽可能多的样式,因为它是分离关注点的标准好习惯,可以压缩和捆绑CSS文件,以及许多其他原因与您放置CSS的普通HTML页面中的原因相同在单独的文件而不是直接在页面上.
我从不使用GWT设计师.我总是喜欢使用干净的代码而不是通常由任何UI代码生成器吐出的疯狂垃圾.
99%的时间,我的小工具都会扩展,Composite因为我正在使用UiBinder或者我正在添加内容Panel.即使我只有一个小部件,我发现更容易扩展Composite并将我的一个小部件添加到SimplePanel.我很少扩展,Widget因为那时你必须调用Document.get().createFooElement()创建一个DOM Element,但我通常会找到Widgets,可以添加到Panels,更容易和safter工作比Elements
每个小部件实现一个扩展的接口IsWidget.每个想要使用它的人都Widget应该依赖于接口,而不是基础类.这提供了一个单一的,无JSNI的抽象.
如果小部件非常简单,我将有一个扩展Composite和实现接口的类.小部件将非常简单并添加一些项目Panel或它将使用UiBinder.
如果小部件具有我想要测试的非平凡逻辑,我使用MVP模式.将有一个演示者类实现窗口小部件的"公共"接口,一个视图接口扩展IsWidget,演示者依赖它,以及一个实现视图接口的视图窗口小部件.
为窗口小部件设置单个"公共"接口的好处是,Composite如果逻辑变得复杂,您可以从实现具有单个类的接口更改为使用MVP,并且使用窗口小部件的任何人都不需要进行更改.
我使用Gin将所有接口和实现连接在一起.
最好用一些代码解释.假设我有一个我想在几个页面上使用的图表,所以我决定为它制作一个可重用的小部件.在显示之前处理RPC响应有一些非平凡的逻辑,所以我想彻底对它进行单元测试.我会用这样的东西:
public interface FinancialChart extends IsWidget {
void setTickerSymbol(String tickerSymbol);
}
class FinancialChartPresenter extends Composite implements FinancialChart {
private final FinancialChartView view;
private final DataServiceAsync service;
@Inject(FinancialChartView view, DataServiceAsync service) {
this.view = view;
this.service = service;
}
@Override public Widget asWidget() {
return view.asWidget();
}
@Override public void setTickerSymbol(String tickerSymbol) {
service.getData(tickerSymbol, new AsyncCallback<FinancialData>() {
@Override public void onFailure(Throwable t) {
// handle error
}
@Override public void onSuccess(FinancialData data) {
SimpleData simpleData = // do some parsing with presentation-specific
// logic, e.g. make dramatic increases or decreases in price have a
// a different color so they stand out. End up with something simple
// that's essentially some (x, y) points that the dumb view can plot
// along with a label and color for each point.
view.drawGraph(simpleData);
}
}
}
interface FinancialChartView extends IsWidget {
void drawGraph(SimpleData simpleData);
}
class FinancialChartWidget extends Composite implements FinancialChartView {
@Override public void drawGraph(SimpleData simpleData) {
// plot the points on a chart. set labels. etc.
}
}
class SomethingWithFinancialChartWidget extends Composite
implements SomethingWithFinancialChart {
interface Binder extends UiBinder<Widget, SomethingWithFinancialChartWidget> {}
@UiField(provided = true) final FinancialChart chart;
@Inject SomethingWithFinancialChartWidget(Binder binder, FinancialChart chart) {
this.chart = chart;
initWidget(binder.createAndBindUi(this));
}
}
// In SomethingWithFinancialChartWidget.ui.xml
<ui:HTMLPanel>
<!-- lots of stuff -->
<mynamespace:FinancialChart ui:field="chart" />
<!-- lots more stuff -->
</ui:HTMLPanel>
class MyPackagesGinModule extends AbstractGinModule {
@Override protected void configure() {
bind(FinancialChart.class).to(FinancialChartPresenter.class);
bind(FinancialChartView.class).to(FinancialChartWidget.class);
}
}
Run Code Online (Sandbox Code Playgroud)
这允许我为它编写非常简单,彻底和快速的JUnit测试,FinancialViewPresenter因为它没有需要JSNI的GWT依赖,JSNI必须在浏览器中运行,作为速度慢得多的GWT测试用例的一部分.你可以创建一个模拟FinancialChartView.
这里需要注意的一点是,由于SomethingWithFinancialChartWidget依赖于接口FinancialChart,它无法实例化该对象,因为它只是一个接口.这就是为什么在Java代码中chart设置的原因.Gin设置从接口到具体类的绑定,因此它可以为构造函数提供实现,然后设置为UiBinder提供所需的对象.@UiField(provided = true)SomethingWithFinancialChartWidgetFinancialChart@InjectSomethingWithFinancialChartWidgetthis.chart
为MVP中的所有接口和实现创建了许多文件,但抽象绝对值得,因为它们可以轻松地对演示者进行单元测试,并允许您更改顶级接口(FinancialChart在此示例中)的实现方式,例如,从单个Composite类更改为MVP,没有客户端需要更改.
我确信有一些实现细节可能不是很清楚或我掩盖的事情,例如GWT测试,所以请发表评论,我可以编辑我的答案进行更新和澄清.