How to use GWT's Editor Framework with gwt-platform?

浪子不回头ぞ 提交于 2019-11-30 07:16:13
Marco Jakob

An approach similar to what was used in an earlier version of the Expenses sample worked for me:

An interface that the view should implement. The wildcard is used so that the presenter does not need to know the concrete view implementation:

import com.google.gwt.editor.client.Editor;
import com.gwtplatform.mvp.client.View;

/**
 * Implemented by views that edit beans.
 *
 * @param <B> the type of the bean
 */
public interface BeanEditView<B> extends View, Editor<B> {

  /**
   * @return a new {@link SimpleBeanEditorDriver} initialized to run
   *         this editor
   */
  SimpleBeanEditorDriver<B, ?> createEditorDriver();
}

Your presenter should look something like this now:

public class MyPresenter extends Presenter<MyPresenter.MyView, MyPresenter.MyProxy> implements MyUiHandlers {
    public interface MyView extends BeanEditView<MyModel>, HasUiHandlers<MyUiHandlers> {}

    @ProxyStandard
    @NameToken(NameTokens.myPage)
    @NoGatekeeper
    public interface MyProxy extends ProxyPlace<MyPresenter> {} 

    private SimpleBeanEditorDriver<MyModel, ?> editorDriver;
    DispatchAsync dispatcher;

    @Inject
    public MyPresenter(EventBus eventBus, MyView view, MyProxy proxy, DispatchAsync dispatcher) {
        super(eventBus, view, proxy);
        getView().setUiHandlers(this);
        this.dispatcher = dispatcher;

        MyModel m = new MyModel();
        m.setId(1L);
        m.setUsername("username");
        m.setPassword("password");

        editorDriver = getView().createEditorDriver();
    }

    ...
}

And the view implmementation:

public class MyViewImpl extends ViewWithUiHandlers<MyUiHandlers> implements
    MyPresenter.MyView {

  public interface Binder extends UiBinder<Widget, MyViewImpl> { }
  private static Binder uiBinder = GWT.create(Binder.class);

  /**
   * The driver to link the proxy bean with the view.
   */
  public interface EditorDriver extends SimpleBeanEditorDriver<MyModel, MyViewImpl> { }

  private final Widget widget;

  public MyViewImpl() {
    widget = uiBinder.createAndBindUi(this);
  }

  @Override
  public SimpleBeanEditorDriver<MyModel, ?> createEditorDriver() {
    EditorDriver driver = GWT.create(EditorDriver.class);
    driver.initialize(this);
    return driver;
  }

  @Override
  public Widget asWidget() {
    return widget;
  }

  ...
}

That's as close as I could get to MVP with GWT's Editor Framework. I couldn't find a way for the view implementation to NOT know the model but I don't think it's really necessary.

If anyone has any improvements on this, I'm glad to hear.


Found some additional comments on GWT Editors. It seems that it might just not be possible to completely separate the model. As Thomas Broyer puts it in his answer to another Editor question:

"MVP is not set in stone (it's not even defined; it was coined by Martin Fowler but he retired the term in favor of two more specific patterns), so you're only violating the rules you gave to yourself. Put differently, the Editor framework as a whole can be seen as violating MVP: each editor know the model, not necessarily the exact instance it's editing (as with ValueAwareEditor or LeafValue), but at least the kind of objects it's an editor of."

The issue is that the Driver.class passed to GWT.create

editorDriver = GWT.create(Driver.class);

must the concrete class that holds all sub-editors, i.e. all the uibinded widgets.

One solution is the following:

The view interface extends the editor interface for the Model object

public interface MyView extends View, ..., Editor<MyModel>

The view implementation MyViewImpl defines a driver type

interface MyDriverImpl extends SimpleBeanEditorDriver<MyModel,MyViewImpl>

The driver is instantiated in MyViewImpl by

SimpleBeanEditorDriver<MyModel,MyView> driver = GWT.create(MyDriverImpl.class);

The parent type

SimpleBeanEditorDriver<MyModel,MyView>

can be used to pass references of the driver to the presenter

MVP says that you use the presenter to completely seperate the model from the view. In addition I'd say that your approach puts logic inside the view... I hope that there's another solution ;)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!