GWT MVP UiBinder - 将参数传递给演示者

时间:2011-09-28 23:46:41

标签: gwt mvp uibinder

我已经开始了一个GWT项目,我决定试试UiBinder。我很难在UiBinder上面放置一个MVP模式。

当我使用GWT-pure-java时:我会使用Gin为我的演示者注入相应的视图。它非常简单,如果我想将一个id传递给演示者,那么我只需将一个id传递给演示者的构造函数。

与UiBinder不太直接。我几乎可以肯定我错过了一些东西,因为很多人都声称UiBinder和MVP是天上的匹配......所以我希望能在这个问题上得到一些可靠的答案; - )

我在几个简单的GWT-UiBinder示例中看到的是,视图是由绑定器创建的,然后是:

  1. 该视图在其构造函数中或通过@UIFactory方法构造演示者。
  2. 相应的演示者被传递给视图(通过一个setter,不用说在构建视图之后)。
  3. 使用第一种方法,如果在视图中构建演示者,如何将id传递给演示者?你会做view.getPresenter().setId(42);,然后主持人会去服务器获取一些信息并要求视图显示它......闻起来很糟糕。

    使用第二种方法,最终会得到一个非直观的对象图,其中不清楚谁是消费者,谁是生产者。此外,在视图需要演示者提供信息的情况下(几乎所有用例都需要这样),人们会做什么:

    //some code would create the presenter pass it the id and then call view.setPresenter
    class MyView {
        void setPresenter(MyPresenter p) {
        this.presenter = p;
        //OK now that i have my presenter how do I ask it to fetch data from the server.
        //do i turn around and do: presenter.setView(this); and then the presenter takes 
        //over and uses the view to display the data?
         }
     }
    

    这同样很臭......很抱歉这篇长篇文章,并提前感谢...

2 个答案:

答案 0 :(得分:6)

你是对的,将View引用它的Presenter看起来似乎有点不干净,并让演示者引用View。

我看到它的方式,以及谷歌开发页面在MVP上的概述有两种风格的MVP:

  1. 有一个不了解其演示者的视图,并用演示者“包装”它。该视图为演示者提供了足够的API来获取/设置它关心的所有数据。此外,演示者必须知道视图可以生成的所有事件类型,以响应用户交互。这是MPV part 1
  2. 的方法
  3. 演示者再次了解视图,但这次只能获取/设置数据容量。演示者不关心视图中的UI事件。相反,演示者为视图提供API,以便在事件以我们的演示者中的“onSomethingHappened()”方式发生时调用/通知它。这允许我们捕获演示者本身中的所有行为/逻辑,并在视图中发生某些事情时根据需要调用它。然后,视图可以以任何合适的方式处理非常低级别的事件 - 无论是使用GWT事件/窗口小部件还是使用元素/ HTML的原始DOM事件(UiBinder / GWT性能最佳实践)。这是MVP part 2
  4. 的方法

    我更喜欢选项2,因为它允许演示者完全专注于必要的行为。视图可以根据需要处理小部件/ html /事件处理,并将其简化为调用演示者的“onSomething()”调用。这些小部件/事件实现可能是简单或复杂的优化事件。演示者不受细节影响(并且未受污染),因为它只是得到通知。我觉得这个选项更清晰地分离了表现和行为。请注意,它也是Observer Pattern的1对1实现,因此View和Presenter之间的互连是必要的。

    至于创作,我觉得Presenter是一个更强大的实体,尽管它扮演观察者的角色。我会创建必要的演示者,然后传递它关注的视图。然后,演示者可以控制视图,并将视图作为自引用传递。

    至于你的制作人/消费者比喻,我认为主持人是消费者。视图生成UI事件(用户交互),演示者通过提供必要的行为进行响应。这应该是视图和演示者之间唯一的联系点 - 视图调用类似“onSomethingHappened()”的方法,并且演示者完成工作。该视图永远不会告诉演示者“fetchData()”或类似的东西。

    我最近刚开始使用UiBinder + MVP,所以这就是我的想法。我希望它有所帮助!

答案 1 :(得分:0)

自从我开始这个帖子并阅读回复以来已经有几天了。我决定采用自己的方法。我想我只是在这里提到它。

再一次,感谢周到的回答......他们很有帮助。

由于filip-fku指出演示者是主要实体,所以我决定在我的mvp对象的生命周期管理期间继续威胁它们。换句话说,视图不会实例化演示者。演示者由其他演示者实例化(在某些时候我将委托给Gin)。

演示者的builder可以访问其相应的视图,并使用视图注入演示者(通过构造函数)。

视图本身要么由builder实例化,要么由UiBinder实例化为更大视图的一部分。在后一种情况下,UiBinder实例化视图,父视图有一个getter。以下是此案例:

/*pojo for the parent ui-binder*/
public class Form implements FormPresenter.View {
@UiField PromptView namePrompt;
@override
PromptPresenter.View getNamePromptDisplay() {
    return namePrompt;  //introduced into this pojo via @UiField
}
//bunch of view code
}//end of the class

然后在FormPresenter中我做:

private void buildNamePrompt() {
  new PromptPresenter(display.getNamePromptDisplay(), etc....);
}

我基本上保持了mvp生命周期类似于纯java方法。一旦我从中获得了一些改进,我将用Gin重构它。

再次感谢。 附:如果您还没有看到上面提到的i / o演示文稿,那么值得一试。

相关问题