我正在使用GWT 2.4与gwt-platform 0.7和gin 1.5.0。
我已经为我的GWT应用程序的动态(实时)翻译构建了一个库。因此,当LocaleChangeEvent
被触发时,每个小部件都会收到通知,然后让我的TranslationDictionary
获取要显示的新字符串。
小部件实际上看起来像这样:
public class LocaleAwareLabel extends Label implements LocaleChangeEventHandler {
TranslationDictionary dictionary;
String translationToken;
public LocaleAwareLabel(TranslationDictionary dictionary, EventBus eventBus, String translationToken) {
this.dictionary = dictionary;
this.translationToken = translationToken;
eventBus.addHandler(LocaleChangeEvent.TYPE, this);
getCurrentTranslationFromDictionary();
}
public void getCurrentTranslationFromDictionary() {
this.setText(dictionary.getTranslation(translationToken));
}
@Override
public void onLocaleChange(LocaleChangeEvent event) {
getCurrentTranslationFromDictionary();
}
}
正如您所看到的:我无法轻松地将此小部件与UiBinder一起使用,此时我在EventBus
中注入TranslationDictionary
和View
并使用@UiField(provided=true)
之类的这样:
@UiField(provided=true)
LocaleAwareLabel myLabel;
@Inject
public MyView(TranslationDictionary dictionary, EventBus eventBus) {
widget = uiBinder.createAndBindUi(this);
myLabel = new LocaleAwareLabel(dictionary, eventBus, "someTranslationToken");
}
我想要的内容:在没有@UiField(provided=true)
的情况下使用我的小部件,所以我可以简单地将它们放在ui.xml
这样的内容中:
<custom:LocaleAwareLabel ui:field="myLabel" translationToken="someTranslationToken" />
我知道我可以通过UiBinder设置translationToken
:
public void setTranslationToken(String translationToken) {
this.translationToken = translationToken;
}
但是由于EventBus
和TranslationDictionary
,我仍然遇到无法使用零参数构造函数的问题。另外我不能在构造函数中调用getCurrentTranslationFromDictionary()
,因为translationToken
的值当然是在构造函数之后设置的。
如果有人可以提供解决方案,可能会提供代码示例,那会很好。
和P.S.我是一个完全注射 - 菜鸟,但从我的理解杜松子酒可能会以某种方式解决我的问题。但我不知道如何。
谢谢!
答案 0 :(得分:6)
目前在依赖注入和UiBinder之间存在一些概念不匹配,但我目前使用它的方式是:
private final Provider<LocaleAwareLabel> labelProvider;
@Inject
public MyView(TranslationDictionary dictionary,
EventBus eventBus,
Provider<LocaleAwareLabel> labelProvider) {
this.dictionary = dictionary;
this.labelProvider = labelProvider;
initWidget(uiBinder.createAndBindUi(this));
}
@UiFactory
public LocaleAwareLabel buildLocaleAwareLabel() {
return labelProvider.get();
}
然后我可以在我的ui.xml中创建任意数量的标签:
<g:HTMLPanel>
<custom:LocaleAwareLabel translationToken="abc"/>
<custom:LocaleAwareLabel translationToken="xyz"/>
</g:HTMLPanel>
在LocaleAwareLabel中,我对翻译令牌使用setter方法,并覆盖onLoad()
:
private String translationToken;
@Inject
public LocaleAwareLabel(TranslationDictionary dictionary, EventBus eventBus) {
this.dictionary = dictionary;
initWidget(uiBinder.createAndBindUi(this));
}
@Override
protected void onLoad() {
super.onLoad();
doSomethingWithTheTranslationToken(); // do this here, not in the constructor!
}
public void setTranslationToken(final String translationToken) {
this.translationToken = translationToken;
}
MyView更改为:
private final LocaleAwareLabelFactory labelFactory;
@Inject
public MyView(TranslationDictionary dictionary,
EventBus eventBus,
LocaleAwareLabelFactory labelFactory) {
this.dictionary = dictionary;
this.labelFactory = labelFactory;
initWidget(uiBinder.createAndBindUi(this));
}
@UiFactory
public LocaleAwareLabel buildLocaleAwareLabel(final String translationToken) {
return labelFactory.create(translationToken);
}
LocaleAwareLabel:
public interface LocaleAwareLabelFactory {
LocaleAwareLabel create(final String translationToken);
}
@Inject
public LocaleAwareLabel(TranslationDictionary dictionary,
EventBus eventBus,
@Assisted String translationToken) {
this.dictionary = dictionary;
initWidget(uiBinder.createAndBindUi(this));
doSomethingWithTheTranslationToken(); // now you can do it in the constructor!
}
在您的Gin模块中,添加:
install(new GinFactoryModuleBuilder().build(LocaleAwareLabelFactory.class));
确保将guice的辅助注入jar(例如guice-assistedinject-snapshot.jar)添加到类路径中。
答案 1 :(得分:5)
目前这是不可能的,因为UiBinder永远不会调用GIN来实例化小部件。为此,您必须使用@UiFactory
方法,或使用@Uifield(provided=true)
提供已构建的实例。
已经要求增强功能以更好地集成这两者。您可以在此处跟踪:http://code.google.com/p/google-web-toolkit/issues/detail?id=6151
作为替代方案,您可以requestStaticInjection
将Provider
注入static
字段,并从构造函数中调用提供程序的get()
:
public class LocaleAwareLabel extends Label {
@Inject Provider<EventBus> eventBusProvider;
@Inject Provider<TranslationDictionary> dictionaryProvider;
private final TranslationDictionary dictionary;
private final EventBus eventBus;
private final string translationToken;
@UiConstructor
public LocaleAwareLabel(String translationToken) {
this(dictionaryProvider.get(), eventBusProvider.get(), translationToken);
}
// For cases where you can use injection, or inject params yourself
@Inject
public LocaleAwarelabel(TranslationDictionary dictionary, EventBus eventBus,
String translationToken) {
this.dictionary = dictionary;
this.eventBus = eventBus;
this.translationToken = translationToken;
}
您可能也对GIN对Assisted-Inject的支持感兴趣,以便更轻松地编写@UiFactory
方法或初始化@UiField(provided=true)
字段。