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:
- The view constructs the presenter either in its constructor or via a
@UIFactorymethod. - 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…
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:
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!