8

我将 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 一起使用,目前我注入EventBusTranslationDictionary在我的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" />

我知道我可以translationToken使用以下方法设置 via UiBinder:

public void setTranslationToken(String translationToken) {
    this.translationToken = translationToken;
}

EventBus但是我仍然有一个问题,因为and ,我不能使用零参数构造函数TranslationDictionary。另外我不能getCurrentTranslationFromDictionary()在构造函数内部调用,因为值translationToken当然是在构造函数之后设置的。

如果有人可以提供解决方案会很好,也许有代码示例。

PS我是一个完全的注射菜鸟,但据我了解,杜松子酒可能会以某种方式解决我的问题。但我不知道怎么做。

谢谢!

4

2 回答 2

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;
}

AssistedInject 示例

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);
}

区域感知标签:

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)添加到您的类路径中。

于 2012-07-11T15:38:28.903 回答
5

目前这是不可能的,因为 UiBinder 永远不会调用 GIN 来实例化小部件。为此,您必须使用@UiFactory方法,或提供已构建的实例@Uifield(provided=true)

已经有人要求增强以更好地整合两者。你可以在这里跟踪它:http ://code.google.com/p/google-web-toolkit/issues/detail?id=6151

作为替代方案,您可以requestStaticInjection将 aProvider注入一个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)字段。

于 2012-07-11T15:01:23.377 回答