I am using GWT MVP to develop an application. I saw we can have two kinds of event handlers in GWT MVP code, but I am not very sure about which kind should I use in which place:
1) HandlerManager (eventBus) EventHandlers (e.g. EditEventHandler
below) in AppController
:
eventBus.addHandler(EditEvent.TYPE,
new EditEventHandler() {
public void onEdit(EditEvent event) {
doEdit(event.getId()); // this would open a new screen, call AsyncService etc
}
});
I understand, these kind of event handlers are used for handling application-wide custom events.
2) GUI/View Event Handlers (e.g. ClickHandler
) in Presenter
, where I handle the GUI event and then fire the application event to invoke its handler as below:
display.getList().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
int selectedRow = display.getClickedRow(event);
if (selectedRow >= 0) {
String id = myDetails.get(selectedRow).getId();
eventBus.fireEvent(new EditEvent(id)); // this in turn would invoke the EditEventHandler above
}
}
});
Now, my questions are:
1) Why do we need to write EventHandler for application events (e.g. EditEvent
), and not add that code directly in the associated GUI event handler (e.g. addClickHandler
)?
2)Can't we write the code for opening new screen, calling AsyncService etc directly in GUI EventHandler method, such as onClick
?
3) Wouldn't that make your code more readable, as the event that is triggered and the work that needs to be done is all in one place i.e.Presenter
and you don't have to go back and forth between your Presenter
code and AppController
code?
AsyncService
in your GUI EventHandler. Just make sure you do it in your Presenter
and not in your View
. However the more complex your app gets the messier this approach might get. You will have many AsyncService calls sprinkled all over your various Presenters
. It might be a better approach to group them in your AppController
so there is 1.) one place to look for and 2.) you can easily test/mock all AsyncService
calls in your AppController
. Presenter
should also be done there without needing to go through AppController
and back. However it still might make sense to put the AsyncService
calls into your AppController
because you might need to do some bookeeping (for example caching the results in LocalStroage
, submitting other Events, etc) and/or notify other screens/components about the loaded data. Think of Events as messages. Here is an example:
You have a View/Presenter pair for displaying a list of records (i.e. RecordListPresenter
). The user clicks on the edit button on one of the records and you have a separate View/Presenter pair for editing the specific record (i.e RecordEditPresenter
). Instead of having a reference from your RecordListPresenter
to your RecordEditPresenter
which would make them aware of each other and increase the coupling the RecordListPresenter
sends a message to edit a record (Edit
event). The AppController
will act as a Mediator and open load the data and open the RecordEditEditor
(it can also only fire an Event with the loaded data and the RecordEditEditor
could reveal itself).
But now imagine that you also have a HeaderPresenter
for displaying some breadcrumb information (like which record it is editing). If you go the "eventless" approach you would need another reference in the RecordListPresenter
and RecordEditPresenter
to it to drive it. With Events
those Presenters
don't have to know that there is a HeaderPresenter
. They just fire Events.
Now in a complex app you might have many of those independend units.