How to Use the Gwt Eventbus

How to use the GWT EventBus

When you divide the project into logical parts (for example with MVP), then the different parts sometimes need to communicate. Typical this communication is done by sending status changes, e.g.:

  • user logged-in / logged-out.
  • user navigated directly via URL to a page, so the menu needs to be updated.

Using the event bus is quite logical in those cases.

To use it you instantiate one EventBus per app which is then used by all other classes. To achieve this use a static field, factory or dependency injection (GIN in case of GWT).

Example with your own event types:

public class AppUtils{

public static EventBus EVENT_BUS = GWT.create(SimpleEventBus.class);
}

Normally you'd also create your own event types and handlers:

public class AuthenticationEvent extends GwtEvent<AuthenticationEventHandler> {

public static Type<AuthenticationEventHandler> TYPE = new Type<AuthenticationEventHandler>();

@Override
public Type<AuthenticationEventHandler> getAssociatedType() {
return TYPE;
}

@Override
protected void dispatch(AuthenticationEventHandler handler) {
handler.onAuthenticationChanged(this);
}
}

and the handler:

public interface AuthenticationEventHandler extends EventHandler {
void onAuthenticationChanged(AuthenticationEvent authenticationEvent);
}

Then you use it like this:

AppUtils.EVENT_BUS.addHandler(AuthenticationEvent.TYPE, new AuthenticationEventHandler()     {
@Override
public void onAuthenticationChanged(AuthenticationEvent authenticationEvent) {
// authentication changed - do something
}
});

and fire the event:

AppUtils.EVENT_BUS.fireEvent(new AuthenticationEvent());

GWT MVP. How to use event bus?

If the point when the presenter needs to get the selected value is when the user makes an action you won't get around using an event. (Altough, maybe both presenters could react to the same event so don't need to use two different ones?)

If it is known when the presenter needs to get the value (a defined step in a workflow), you could to it like this:

Keep a reference to the views in the ClientFactory:

public class ClientFactoryImpl implements ClientFactory {
private static final EventBus eventBus = new SimpleEventBus();
/* The views */
private static final SampleView sampleView = new SampleView();
....

public ClientFactoryImpl(){
eventBus.addHandler(ReleaseAddedEvent.type, sampleView);
....
}

// getter and setters
}

So in the Presenter you can get a reference to the view: SampleView view = MyEntryPoint.getClientFactory().getSampleView(); and then you can just call a method from the view which returns the selected value.

GWT Event Bus for which benefits

No event bus

Example: You can buy apples from the farm directly.

Button maintains the collection of listeners. Button is aware about all listeners and needs to notify them in the loop. Button is directly coupled with the handlers.

Event bus

Example: You buy apples from a store and store buys apples from the farm. The store is a broker between you and the farm. You are not aware about the farm. The farm is not aware about you.

Event bus is broker between the event producer and event consumer. Event producer is aware about event bus but not all event consumers.

Button is not aware about the listeners. It's aware about EventBus only.
Handlers are not aware about the Button. They are aware about the bus.

Summary:

Applications without plugins may be implemented without event bus.

Applications with plugin support should be implemented with the event bus as it's not known before hand how many plugins are connected to the event producer.

How to use EventBus for non-Presenter class in GWTP?

I' dont use GWTP, but I guess the following is ok.

@Inject private EventBus eventBus

should work (if you don't use it in SearchDialogBox constructor right away).

Otherwise try to find out which class in GWTP extends com.google.gwt.inject.client.Ginjector. Assuming it is called "MyInjector" just write :

private EventBus eventBus = MyInjector.INSTANCE.getEventBus();

How do you use GWT's SimpleEventBus or EventBus?

A SimpleEventBus provides the very basic functionality of storing a collection of handlers, and calling event.dispatch() with all of the relevant handlers when appropriate. I wouldn't say that you "set EventBus to listen for events" from the parent widget. The SimpleEventBus doesn't have a concept of a "parent." Instead, you pass around a reference to your SimpleEventBus. Then, any object can "fire an event" with the SimpleEventBus.fireEvent method. There's no hierarchy.

Similarly, any object can listen for those events with SimpleEventBus.addHandler(). This is closest to your #4 - addHandler takes a type of event and a handler, so whenever that type of event is passed to fireEvent (by something in your app), that handler will be passed to the event. Note that the Event is what calls the handler, NOT the EventBus! The EventBus just calls event.dispatch(theHandler), and the programmer of the event is responsible for calling the proper function in theHandler. Your #5 is inaccurate, at least for a SimpleEventBus - SimpleEventBus does not inspect the events at all, except to see which handlers to call. It doesn't know about any child widgets or any app logic, and never changes the type of an Event.

Your logic about seeing which region was picked would not be appropriate in an EventBus - instead, you would make a handler that does the logic and listens for ClickEvents. Then, that handler could tell the selected region that it was selected directly, or you could create your own RegionSelectionEvent that you could fire along an EventBus, and then all of the regions could be informed that a RegionSelection has occurred, and your logger could get a notification, or your server monitor could get the notification and notify the boss that someone selected a region, or whatever. If you just need to deselect one region and select another, an eventbus is overkill.

On the other hand, something like a "resize" event makes a lot of sense, since all of your widgets might need to know about it.

GWT, how to fire event from widget or composite using EventBus from HandlerManager

It does not work because your FileUploadWidget uses it's own EventBus and not GWTP one that is also used in all of your Presenters.

There are two solutions:

  1. Don't use fireEvent(new IndicatorStartEvent("Message")) but use eventBus.fireEvent(new IndicatorStartEvent("Message")) on the injected EventBus inside of your Widget.

  2. Add the IndicatorStartEvent handler to your FileUploadWidget directly instead of using addRegisteredHandler on your Presenter.

I prefer solution 2:

public class FileUploadWidget extends Composite {
MaterialFileUploader uploader = new MaterialFileUploader();

@Inject
public FileUploadWidget(String triggerId) {
super();
initWidget(uploader);
Window.alert("TEST Start");
fireEvent(new IndicatorStartEvent("Message"));
}
}

In the Presenter or to be precise the View which uses your FileUploadWidget, you add a handler directly to the FileUploadWidget:

public class UploadView extends ViewWithUiHandlers<UploadUiHandlers> implements UploadPresenter.MyView,IndicatorStartEvent.IndicatorHandler {

@UiField
FileUploadWidget uploadWidget;

@Inject
public UploadView(final Binder binder) {
widget = binder.createAndBindUi(this);
uploadWidget.addHandler(new IndicatorStartEvent.Handler(),this);
}

public void onIndicatorProgressStart(IndicatorStartEvent event) {
MaterialToast.fireToast("Indicator start: " + event.getMessage());
}
}

Which GWT EventBus should I use?

Generally you should use the one in com.google.web.bindery. The only version used to be in com.google.gwt.event, but when RequestFactory and AutoBeans were moved out of GWT itself and into com.google.web.bindery so they could work in non-GWT clients.

If you use the com.google.web.bindery version in your presenters and such, it will make it easier to use outside GWT apps, should you need to. You'll also not get deprecation warnings when passing that instance to PlaceController and other classes that use EventBus.

Which GWT EventBus should I use?

Generally you should use the one in com.google.web.bindery. The only version used to be in com.google.gwt.event, but when RequestFactory and AutoBeans were moved out of GWT itself and into com.google.web.bindery so they could work in non-GWT clients.

If you use the com.google.web.bindery version in your presenters and such, it will make it easier to use outside GWT apps, should you need to. You'll also not get deprecation warnings when passing that instance to PlaceController and other classes that use EventBus.

Check if GWT EventBus has an EventHandler or not

The addHandler() method returns a HandlerRegistration the removeHandler() method of which you can use to remove your handler.



Related Topics



Leave a reply



Submit