我已经开始了一个GWT项目,我决定试试UiBinder。我很难在UiBinder上面放置一个MVP模式。
当我使用GWT-pure-java时:我会使用Gin为我的演示者注入相应的视图。它非常简单,如果我想将一个id传递给演示者,那么我只需将一个id传递给演示者的构造函数。
与UiBinder不太直接。我几乎可以肯定我错过了一些东西,因为很多人都声称UiBinder和MVP是天上的匹配......所以我希望能在这个问题上得到一些可靠的答案; - )
我在几个简单的GWT-UiBinder示例中看到的是,视图是由绑定器创建的,然后是:
@UIFactory
方法构造演示者。使用第一种方法,如果在视图中构建演示者,如何将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?
}
}
这同样很臭......很抱歉这篇长篇文章,并提前感谢...
答案 0 :(得分:6)
你是对的,将View引用它的Presenter看起来似乎有点不干净,并让演示者引用View。
我看到它的方式,以及谷歌开发页面在MVP上的概述有两种风格的MVP:
我更喜欢选项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演示文稿,那么值得一试。