【问题标题】:Using GWT Deferred Binding to replace uibinder template使用 GWT Deferred Binding 替换 uibinder 模板
【发布时间】:2012-08-21 22:07:23
【问题描述】:

使用 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。这些组件将不可重用或扩展。主题仅适用于简单的自定义标题。

想法?解决方案?谢谢!

【问题讨论】:

    标签: gwt uibinder deferred


    【解决方案1】:

    让我告诉你 Google 打算让你替换类模板的方式。

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

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

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

    实际上,我通常所做的不是在基类中而是在扩展类中添加任何 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 中执行模板替换 thro replace-with,因为已经有方便的途径。

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

    【讨论】:

    • 我明白你在说什么,并且完全理解你关于我如何实现类结构的论点。我不明白的是您的解决方案如何帮助我在编译时切换外观?我有两个完全独立的主题,我不想在为一个主题或另一个主题执行构建之前更改源代码。目前,我们只有自定义的标题,但将来我们可能会有其他需要更改外观的类。所以我需要一个配置属性来定义应该应用哪个主题。
    • 让可替换的扩展 ui 类位于不同的模块中。一个用于 android 的入口点模块,另一个用于 chromebook,另一个用于普通浏览器等。另一个用于 Firefox-only-compilation 的开发/调试。
    【解决方案2】:

    我再次查看了 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" />
    

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

    【讨论】:

      【解决方案3】:

      如果您希望 View 基于 useragent 属性绑定到 Viewimpl 则

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

      【讨论】:

        猜你喜欢
        • 2011-09-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-07
        • 1970-01-01
        • 2012-07-31
        相关资源
        最近更新 更多