GWT, MVP, and UIBinding - How to get the best of all worlds
With MVP, you normally bind the View (UI) with the Presenter in the Presenter. However with the latest version of GWT, especially with UIBinding, you can do the following in the View:
@UiHandler("loginButton")
void onAboutClicked(ClickEvent event)
{
// my login code
}
Which basically exchanges a lot of anonymous inner class code for some quick annotation code. Very nice!! The problem is that this code is in the view and not the presenter...
So I thought maybe:
@UiHandler("loginButton")
void onAboutClicked(ClickEvent event)
{
myPresenter.onAboutClicked(...);
}
But there are several problems with this approach. The most important, you blur the lines between View and Presenter. Who does which binding, in some cases it's the View, in others it's the presenter (binding to events not in your current view but that need to be attached - for example a system wide update event).
You still get the benefit of being able to unit test your presenter, but at what cost. The responsibilities are messy now. For example the binding is sometimes in the Vie开发者_StackOverfloww and others times in the Presenter level. I can see the code falling into all kinds of chaos with time.
I also thought of extending the Presenter to the View, so that you could do this in the View. The problem here is that you lose the Presenter's ability to run standard unit tests! That's a major issue. That and the lines again become blurred.
So my question, does anyone have a good method of taking advantage of the annotation from UIBinding within the MVP pattern without blurring the lines and losing the advantages of the MVP pattern?
I tend to use the @UiHandler
approach only when the Handler does view-specific stuff, like adding style names, etc. For other purposes (adding validation, etc), I stick with the old approach of adding the appropriate Handlers in the Presenter.
I'd recommend reading through one of the many threads on GWT Google Group about MVP and UiBinder, such as this one.
To be honest I don't use the @UiHandler
annotation much, because as you said, it starts to muddy the lines between the View and the Presenter. It's totally fine to use, and a great shortcut if you don't particularly care about sticking to the pattern, though.
The presenter.onAboutClicked()
route is definitely an option, but then you might as well define the handler in the presenter in the first place.
or if you are looking for a real implementation on how to make it work check out this blog post, I have to say that up until I found it everything else was still noise in my learning.
gwt 2.0.x is a great improvement on gwt 1.x but I still believe google has some way to go with their documentation and guidance since as we have seen with uibinder and mvp, it leaves a lot to the imagination on how to make things work.
hope the link shades a little bit more light on what u need.
If using the MVP pattern, your SomeView interface should have an inner Presenter interface defined which in turn in implemented by your presenter (Activity class). So inside the view do the following:
interface SomeView extends IsWidget
public interface Presenter{
...all the methods
public void doSomeAction(SomeView view);
}
...view methods
}
now in the SomeViewImpl class, attach a handler
@UiHandler("some_button")
void onClickSomeButton(ClickEvent e){
// call the presenter method (you have access to it in the ViewImpl class
presenter.doSomeAction(this);
}
It looks a bit long, but the pattern works great.
It's often useful for the view to delegate some of its actions to the presenter using a pattern sometimes referred to as a "supervising controller".
This has also been advocated by Google as a good way to benefit from the nice @UiHandler annotation at your disposal when you use !UiBinder. The main difference with the original presenter pattern is that the view keeps a link back to the presenter in order to invoke some of its methods, instead of the presenter registering callbacks towards the view.
https://github.com/ArcBees/GWTP/wiki/UiHandlers
精彩评论