简体   繁体   English

GWT:使用单独的mvp构建小部件

[英]GWT: Building widgets with separated mvp

I'm trying to build a gwt widget with separated model, view and presenter. 我正在尝试使用分离的模型,视图和演示者构建gwt小部件。

I'm using just one class for all of these components so far: 到目前为止,我只使用了一个类用于所有这些组件:

A compact example: 一个紧凑的例子:

public class MyCellSelectableTable extends Composite {

   private WhatEverRepresentation selectedCell;

   public MyCellSelectableTable() {

      Grid myTable = new Grid(2,2);
      /*
       * Some code to realize a table with cell selection
       * ...
       */

     initWidget(myTable);
  }
}

In my appreciation the information "selectedCell" (and in my project many other data) should be stored in a separate model. 在我看来,“selectedCell”(以及我的项目中的许多其他数据)的信息应该存储在一个单独的模型中。 How can I implement this structurally correct, so it still is a widget but with an encapsulated mvp architecture? 我怎样才能在结构上正确实现这一点,所以它仍然是一个小部件但是有一个封装的mvp架构?

In one of my projects I was asked to design a spinner item which is dressed to look good on a mobile web app. 在我的一个项目中,我被要求设计一个旋转项目,该项目在移动网络应用程序上看起来很好看。 Then we realized we actually need another view for our spinner which is 'thinner' as well. 然后我们意识到我们实际上需要另一个我们的旋转器视图,它也是“更薄”的。 So I have tried to aplly the MVP approach to my widget implementation which worked well for me. 所以我试图将MVP方法应用于我的小部件实现,这对我来说很有用。 This one below is a very simple example not for production use just for the sake of demonstration 下面这个是一个非常简单的例子,不仅仅是为了演示而用于生产

Define a Presenter and a View interface as in MVP pattern. 以MVP模式定义Presenter和View界面。 The point here is to make the view implementations dumb so they can be switched without a hassle. 这里的要点是使视图实现变得愚蠢,以便可以毫不费力地切换它们。 Note that Spinner is not actually a Widget but it implements IsWidget which means it will be treated like a widget but in fact we will be passing the reference of our view implementation. 请注意,Spinner实际上不是一个Widget,但它实现了IsWidget,这意味着它将被视为一个小部件,但实际上我们将传递我们的视图实现的引用。

public class Spinner implements IsWidget, SpinnerPresenter{
    interface View{
        Widget asWidget();
        void stepUp(int step);
        void stepDown(int step);
        void setValue(int value);
        void setPixelSize(int width,int height);
    }   
    View view;
    int value;  
    public Spinner() {
        view = new SpinnerImpl(this);
        view.setValue(0);
    }   
    public int getValue() {
        return value;
    }   
    public void setValue(int value) {
        if (value == this.value)
            return;
        this.value = value;
        view.setValue(value);
    }
    public void setPixelSize(int width, int height){
        view.setPixelSize(width,height);
    }
    @Override
    public void downButtonClicked() {
        value--;
        view.stepDown(1);
    }
    @Override
    public void upButtonClicked() {
        value++;
        view.stepUp(1);
    }
    @Override
    public Widget asWidget() {
        return view.asWidget();
    }
}

And the view Implementation itself which implements the view interface defined in Spinner class. 视图实现本身实现了Spinner类中定义的视图接口。 Notice how we delegate user events to Spinner class to be handled over the SpinnerPresenter interface. 请注意我们如何将用户事件委托给Spinner类,以便通过SpinnerPresenter接口进行处理。

public class SpinnerImpl extends Composite implements Spinner.View{
    private TextBox txtBox;
    private Button upButton,downButton;
    private HorizontalPanel panel;
    private SpinnerPresenter presenter;
    public SpinnerImpl(SpinnerPresenter presenter){
        this.presenter = presenter;
        upButton = new Button("up");
        downButton = new Button("down");

        txtBox = new TextBox();
        txtBox.setEnabled(false);

        panel = new HorizontalPanel();
        panel.add(upButton);
        panel.add(txtBox);
        panel.add(downButton);

        addHandlers();
        initWidget(panel);      
    }   
    private void addHandlers() {
        upButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                presenter.upButtonClicked();
            }
        });
        downButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                presenter.downButtonClicked();
            }
        });     
    }
    @Override
    public void stepDown(int step) {
        txtBox.setValue(Integer.parseInt(txtBox.getValue())-1+"");
    }
    @Override
    public void stepUp(int step) {
        txtBox.setValue(Integer.parseInt(txtBox.getValue())+1+"");
    }
    @Override
    public void setValue(int value) {
        txtBox.setValue(0+"");
    }
}

SpinnerPresenter interface : SpinnerPresenter界面:

public interface SpinnerPresenter {
    void upButtonClicked();
    void downButtonClicked();
}

Finally to add my widget to rootpanel. 最后将我的小部件添加到rootpanel。 Notice I can add spinner class as if it was a widget 请注意,我可以添加微调器类,就好像它是一个小部件

Spinner s = new Spinner();
RootPanel.get().add(s);

Now if i wanted to change the way my spinner item looks, change orientation, maybe add a fancy animation for spinning etc, I need only to change my View Implementation. 现在,如果我想改变我的微调器项目的外观,改变方向,可能为旋转等添加一个奇特的动画,我只需要改变我的View实现。 Last but not least when it comes to testing my widget this approach will help since I can easily mockup my view. 最后但并非最不重要的是,在测试我的小部件时,这种方法将有所帮助,因为我可以轻松地模拟我的视图。

I recommend you read the following MVP article if you haven't already (and forgive me if you have): http://code.google.com/webtoolkit/articles/mvp-architecture.html http://www.gwtproject.org/articles/mvp-architecture.html 我建议您阅读以下MVP文章,如果您还没有(如果有的话,请原谅我): http: //code.google.com/webtoolkit/articles/mvp-architecture.html http://www.gwtproject。组织/用品/ MVP-architecture.html

Believe me it's worth it to go ahead and separate out your model, view, and presenter. 相信我,继续分离您的模型,视图和演示者是值得的。 The problem always seems simple enough to have in one class, but when I've tried that I always end up separating things out. 这个问题在一个课程中似乎总是很简单,但是当我尝试过时,我总是把事情分开。 You'll appreciate having a better separation of concerns and the flexibility it offers. 您会感谢您更好地分离关注点和提供的灵活性。

FYI, the cell widgets in GWT are built with MVP internally. 仅供参考,GWT中的单元小部件是在内部使用MVP构建的。 A CellList (for instance) is the "view" part and instantiates an internal presenter. CellList (例如)是“视图”部分并实例化内部呈现器。

Also, this session from Google I/O 2010 was eye opening for me: http://www.google.com/events/io/2010/sessions/gwt-continuous-build-testing.html 此外,Google I / O 2010的这次会议对我来说是开放的: http//www.google.com/events/io/2010/sessions/gwt-continuous-build-testing.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM