1

使用 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. 我是否使用了延迟绑定,它是如何设计使用的?我确实使用与我正在做的类似的外观模式进行了评估,但对于我需要做的事情来说似乎完全是矫枉过正,而且我已经编写了两个自定义 uibinder。这些组件将不可重用或扩展。主题仅适用于简单的自定义标题。

想法?解决方案?谢谢!

4

3 回答 3

3

让我告诉你谷歌让你替换类模板的预期方式。

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

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

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

实际上,我通常所做的不是在基类中而是在扩展类中包含任何 GWT.create - 这样

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

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

这背后的原理是:

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

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

这条规则的结果是你不能扩展一个 uibinded 类而不必重新实现模板。

假设您有一个带有 uibinder 的布局良好的对话框。并且您希望在不改变外观的情况下利用它进行细微的调整。不幸的是,扩展对话框必须复制基类的模板文件,即使您不打算进行任何 ui/布局更改。

我认为您不应该在 gwt.xml 中通过替换来执行模板替换,因为已经有一种方便的方法。

您正在做的事情令人困惑,我认为我不会花时间分析它。

于 2012-08-22T04:42:12.653 回答
0

我再次查看了 GWT外观设计模式,并意识到我并没有真正理解替换是如何工作的。我认为它正在用另一个类的一个具体实现替换一个类。但仔细观察,我发现需要有一个使用 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" />

它正在工作,我很高兴,但有什么改进的想法吗?

于 2012-08-22T22:24:47.223 回答
0

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

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

于 2014-02-21T13:28:16.623 回答