使用GWT延迟绑定替换uibinder模板

时间:2012-08-21 22:07:23

标签: gwt uibinder deferred

使用GWT 2.4.0我试图使用延迟绑定规则将uibinder模板替换为另一个。

我想出这样做的方法是为每个uibinder模板创建一个返回uibinder实例的具体类。这是一个例子。

public class ThemeOneUiBinderImpl {

    @UiTemplate("ThemeOne.ui.xml")
        interface ThemeOneUiBinder extends UiBinder<Widget, PageToTheme> {
    }

    private static ThemeOneUiBinder uiBinder = GWT.create(ThemeOneUiBinder.class);

    public static UiBinder<Widget, PageToTheme> getImpl() {
        return uiBinder;
    }
}

然后我有一个基本相同的第二个类叫做ThemeTwoUiBinderImpl。我的类引用ThemeOneUiBinderImpl并调用getImpl()。createAndBindUi(this)

以下延迟绑定规则          

<replace-with class="package.ThemeTwoUiBinderImpl">
    <when-type-is class="package.ThemeOneUiBinderImpl"/>
    <when-property-is name="theme" value="theme2"/>
</replace-with>

有了这些规则,当我编译时,我看到排列的数量加倍,所以它正在做某事......但是当我加载页面时,theme1 uibinder仍在加载。我有两个问题:

  1. 为什么不工作?
  2. 为什么排列数会翻倍?我认为通过将属性设置为theme2,它只会编译theme2的排列,但它是否为两者编译?
  3. 我是否使用延迟绑定如何设计使用?我确实使用外观模式进行了评估,这与我正在做的类似,但是对于我需要做的事情似乎完全矫枉过正,我已经编写了两个自定义uibinders。这些组件不可重复使用或扩展。主题仅适用于简单的自定义标题。
  4. 思考?解决方案?谢谢!

3 个答案:

答案 0 :(得分:3)

让我告诉你谷歌让你替换课堂模板的方法。

要替换uibinded java类的ui模板,只需扩展该类。这有点像MVP对模板作为视图和代码作为模型的态度。有些。我们的想法是,您可以随时在模型上替换视图,而无需更改模型,也不会禁止您添加到模型中。

我所做的是创建一个带有默认/虚拟模板的基类。

如果扩展类与基类不在同一个包中,则基类的uibinded fields / resources /方法必须是公共的。

事实上,我通常做的是在基类中没有任何GWT.create,但在扩展类中 - 所以

  • 我可以使基础抽象(如果在抽象类上完成,GWT.create会变暗)。
  • 我根本不需要创建模板。该类充满了uibinder注释,如@ uifield,@ iyhandler,@ uichild,blah blah,但该类没有模板xml。

然后我扩展基类,用ui模板创建一个uibinder类,其中ui模板中的字段/资源完全匹配基类中的uifield / resources以及我添加到扩展类中的任何字段/资源

这背后的原则是:

  

基础uibinded类的任何完善扩展必须具有互惠的ui模板,其中模板必须完全重新实现基类的ui字段/资源,无论基类是否已具有其自己的ui模板。

当我说“完成”时,意味着在该扩展类的模板上调用了GWT.create方法。

此规则的结果是,您无法在不必重新实现模板的情况下扩展uibinded类。

假设你有一个带有uibinder的精美布局对话框。而你希望利用它来扩展微调,而不会改变外观。遗憾的是,即使您不打算进行任何ui /布局更改,扩展对话框也必须复制基类的模板文件。

我认为你不应该在gwt.xml中执行模板替换thro replace-with,因为已经有了方便的方法。

你在做什么是混淆,我认为我不会花时间分析它。

答案 1 :(得分:0)

我再次回顾了GWT appearance design pattern,并意识到我并不真正理解替换是如何工作的。我认为它正在用另一个替换一个类的一个具体实现。但仔细观察我发现需要有一个使用GWT.create创建的抽象类或接口。理解和思考外表,因为我会用反射做同样的事情,这真的帮助我弄清楚了。

另外......正如Blessed Geek指出的那样,如果你有一个抽象基础,那么GWT.create会失败,如果你的类没有被正确替换,那就是你想要的。

我现在在视图中有以下内容

public interface MyHeaderAppearance {
    UiBinder<Widget, MyHeaderView> getUiBinder();
    public int getHeight();
}

private final LoginPageAppearance appearance;

public MyHeaderView() {
    appearance = GWT.<MyHeaderAppearance> create(MyHeaderAppearance.class);
}

public void render() {
    panel.add(appearance.getUiBinder().createAndBindUi(this))
}

我的主题实现只是在名为MyHeaderAppearanceImpl的类中实现了MyHeaderAppearance接口。为了支持多个主题,我在每个主题包中都有每个主题的包和一个MyHeaderAppearanceImpl的实例。

然后我将替换像我这样的主题实现代码

ThemeOne.gwt.xml
<module>
    <replace-with  class="theme1.MyHeaderAppearanceImpl">
        <when-type-is class="MyHeaderAppearance"/>
    </replace-with>
</module>

并在我的主模块中包含这样的主题

<inherits name="theme.ThemeOne" />

这很有效,我很高兴,但是有什么改进的想法吗?

答案 2 :(得分:0)

如果您希望View基于useragent属性绑定到Viewimpl,那么

我想分享一个我尝试过的方法,首先,不是将视图映射到viewimpl,你可以将它绑定到viewprovider,然后根据用户代理值,你可以返回适当的实例来绑定到。我实现了这在示例应用程序中及其目前正常工作。