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

发布于 2024-12-06 23:01:10 字数 1100 浏览 1 评论 0原文

我已经开始了一个 GWT 项目,我决定尝试一下 UiBinder。我很难在 UiBinder 之上建立 MVP 模式。

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

UiBinder 就不那么简单了。我几乎可以肯定我错过了一些东西,因为很多人都声称 UiBinder 和 MVP 是天作之合......所以我希望在这个问题上得到一些可靠的答复;-)

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

  1. 视图在其构造函数中或通过 @UIFactory 方法构造呈现器。
  2. 相应的presenter被传递给view(通过setter,不用说是在view构造之后)。

使用第一种方法,如果在视图中构造演示者,如何将 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?
     }
 }

这同样很臭……抱歉,帖子很长,提前感谢……

I've started a GWT project, I've decided to give the UiBinder a try. I'm having a difficult time laying an MVP pattern on top of UiBinder.

When I was using GWT-pure-java: I'd use Gin to inject my presenter with the corresponding view. It was pretty straight forward, and if I wanted to pass an id into the presenter, then I would simply pass an id into the presenter's constructor.

Not so straight forward with UiBinder. I'm almost certain that I'm missing something, because lots of people are claiming that UiBinder and MVP are a match made in heaven...so I'm hoping to get some solid responses on this query ;-)

What I've seen in several trivial GWT-UiBinder examples, is that the view is created by the binder then either:

  1. The view constructs the presenter either in its constructor or via a @UIFactory method.
  2. The corresponding presenter is passed to the view (via a setter, needless to say after the view is constructed).

With the first approach, how does one pass an id to the presenter if the presenter is being constructed in the view? Would you do view.getPresenter().setId(42);, and then the presenter would go to the server get some info and ask the view to display it...smells bad.

With the second approach, one would end up with a non-intuitive object graph in which it is not clear who is the consumer and who is the producer. Also, in situations where the view requires information from the presenter (almost all use-cases require this) what would one do:

//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?
     }
 }

This is equally smelly...Sorry for the long post, and thanks in advance...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

恬淡成诗 2024-12-13 23:01:10

你是对的,让视图引用其演示者,并让演示者引用视图确实看起来有点不干净。

在我看来,以及 MVP 上的 google 开发页面如何概述 MVP 有两种风格:

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

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

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

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

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

You're right in that it does seem a bit unclean to have both a View reference its Presenter, and have the presenter reference the View.

The way I see it, and how the google dev pages on MVP outline there are two flavours of MVP:

  1. Have a view that doesn't know about its presenter, and "wrap" it with a presenter. The view provides a sufficient API for the presenter to get/set all the data it cares about. Additionally the presenter must know about all event types the view can generate, in order to respond to user interaction. This is the method of MPV part 1.
  2. The presenter once more knows about the view, but this time only in a get/set data capacity. The presenter does not concern itself with the UI events in the view. Instead, the presenter provides an API for the view to call/notify it when events happen in the form of "onSomethingHappened()" methods in our presenter. This allows us to capture all behaviour/logic in the presenter itself, and invoke it as necessary when something happens in the view. The view can then handle events at a very low level in any way suitable - whether using GWT events/widgets or raw DOM events with elements/HTML (UiBinder/GWT performance best practices). This is the method of MVP part 2.

I prefer option 2 as it allows the presenter to be purely focused on the necessary behaviour. The view can deal with widgets/html/event handling as necessary and simplify it to calls to "onSomething()" calls for the presenter. Those widget/event implementations might be simple or complex and optimized events. The presenter is unaffected (and unpolluted) by the detail, as it just gets notified. I feel this option is a cleaner separation of presentation and behaviour. Note it's also a 1 to 1 implementation of the Observer Pattern, so the interconnection between View and Presenter is necessary.

As for creation, I feel the Presenter is the stronger entity despite it playing the Observer role. I would create the necessary presenter and then pass it the view of concern. The presenter can then take control of the view, and pass the view a self reference.

As for your producer/consumer analogy I think the presenter is the consumer. The view produces UI events (user interaction) and the presenter responds by providing the necessary behaviour. That should be the only point of contact between the view and presenter - the view calls methods like "onSomethingHappened()" and the presenter does the work. The view would never tell the presenter "fetchData()" or anything like that.

I've just started using UiBinder + MVP recently myself, so this is just what I think. I hope it helps!

绾颜 2024-12-13 23:01:10

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

再次感谢您的深思熟虑的回复……他们很有帮助。

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

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

视图本身要么由构建器实例化,要么由 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....);
}

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

再次感谢。
PS,如果您还没有看过上面提到的 I/O 演示,那么值得一看。

It has been a few days since I started this thread and read the responses. I've decided on my approach. And I'd thought I just mention it here.

Once again, thanks for the thoughtful responses...they were helpful.

As filip-fku pointed out presenters are the main entity, so I decided to continue to threat them as such during the life-cycle management of my mvp objects. In other words, the views do not instantiate the presenters. The presenters are instantiated by other presenters (at some point i'll delegate to Gin).

The builder of a presenter has access to its corresponding view, and injects the presenter (via constructor) with the view.

The views themselves are either instantiated by the builder or instantiated by UiBinder as part of a larger view. In the latter case where UiBinder instantiates the view the parent view has a getter. Here is an example of this case:

/*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

Then in the FormPresenter I do:

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

I have essentially kept the mvp life-cycle similar to the pure java approach. Once I get some milage out of this, I'll refactor it with Gin.

Thanks again.
P.S. if you haven't seen the i/o presentation mentioned above, it is worth checking out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文