Another simple trick I use when I need multiple events that have the same payload and handler methods, is to not declare the TYPE as a static member of the event. Instead I declare it elsewhere (anywhere really) and pass it to the event's constructor. Really simple, but can dramatically cut down on boilerplate.
On Jun 27, 9:05 am, Thomas Broyer <[email protected]> wrote: > A few comments > > On 27 juin, 13:53, Paul Schwarz <[email protected]> wrote: > > > When using the EventBus, for each event type in your system you will > > create a Class (a GwtEvent) and an Interface (the corresponding > > EventHandler). > > > It is a bit of a nuisance maintaining two java files for each event. > > Not necessarily 2 files. As you show below, it's becoming common usage > to declare the handler as an inner/nested interface of the event > class. > > > So I propose to simplify it by having one abstract event class and > > then ONLY ONE class for each event, instead of two. Note that your > > actual usage of your new style event class stays the same, so there is > > no refactoring required there. > > That's not totally accurate, see below. > > > ___________________________________________ > > 1. > > In your com.company.project.shared package create this file: > > > import com.google.gwt.event.shared.EventHandler; > > import com.google.gwt.event.shared.GwtEvent; > > > public abstract class AbstractEvent > > <E extends GwtEvent<H>, H extends AbstractEvent.AbstractHandler<E>> > > extends GwtEvent<H> { > > > public static interface AbstractHandler<E> extends EventHandler { > > void handleEvent(E event); > > } > > The problem with such a generic interface is that you can't implement > 2 of them on the same class. For instance, in my presenters I > generally create an inner Handlers class implementing all event > handler interfaces I need: > class MyPresenter { > private class Handlers implements > PlaceChangeRequestedEvent.Handler, PlaceChangeEvent.Handler, > EmployeeRecordChanged.Handler { > public void onPlaceChange(PlaceChangeEvent event) { ... } > public void onPlaceChangeRequested(PlaceChangedRequestedEvent > event) { ... } > public void onEmployeeChanged(EmployeeRecordChanged event) > { ... } > } > > �...@inject > public MyPresenter(HandlerManager eventBus) { > Handlers handlers = new Handlers(); > eventBus.addHandler(PlaceChangeRequestedEvent.TYPE, handlers); > eventBus.addHandler(PlaceChangeEvent.TYPE, handlers); > eventBus.addHandler(EmployeeRecordChanged.TYPE, handlers); > } > > } > > Using a generic handleEvent method makes this impossible. Well, not > impossible, but cumbersome, as you have to do some if/else with > instanceof in your handler: > public void handleEvent(AbstractEvent event) { > if (event instanceof CalendarChangeRequestEvent) { > CalendarChangeRequestEvent ccre = > (CalendarChangeRequestEvent) event; > ... > } else if (event instanceof EmployeeRecordChange) { > EmployeeRecordChange erc = (EmployeeRecordChange) event; > ... > } > } > > I'm not saying this is a show blocker, but it can then imply some > refactoring, which is not what you "promised" above ;-) > > I'm not saying this is a show blocker, but I nonetheless suspect it > could be an issue, otherwise GwtEvent would have gone this way from > the beginning, or the RecordChangedEvent recently introduced. > I know some people complained about not being able to implement two > ValueChangeHandler on the same class (in this case you'd check the > event's source to "disambiguate" the events). > > Personally I'm using a single inner class implementing all handlers > instead of many anonymous handler classes, because I know a class has > a cost in the output JavaScript cost. I can't tell "how many" it costs > and whether the cost is negligible, and I know it costs less in each > GWT release due to compiler optimizations (-XdisableClassMetadata, GWT > 2.1 introduces some clinit pruning AFAICT), but still, it doesn't make > my code less readable (not particularly more readable either) and > implies only one class initialization and instantiation instead of, in > the above example code, three. > See for > instance:http://code.google.com/p/google-web-toolkit/wiki/ClassSetupAndInstant...http://code.google.com/p/google-web-toolkit/wiki/AggressiveClinitOpti...http://code.google.com/p/google-web-toolkit/wiki/ClinitOptimization > > All in all, I don't think it's really worth it, you're only saving 6 > lines of code (3 for the handler declaration, and 3 for the > dispatchEvent implementation) with no substantial gain as a result. > > > > > > > @SuppressWarnings("unchecked") > > @Override > > protected void dispatch(H handler) { > > handler.handleEvent((E) this); > > } > > > } > > > ___________________________________________ > > 2. > > This is what an actual event class will look like. I think you'll > > agree that this is much simpler than before. Notice we've even got rid > > of getter methods for the attributes and replaced them with public > > final fields instead; this is because we're never changing the event > > data, so it CAN be declared public final, AND that reduces the bulk of > > the class too: > > Again, you're only saving a few lines of code (which an IDE would > generate and maintain for you) without substantial gain (getters would > be inlined anyway by the GWT compiler), but breaking the common Java > coding practice (or more broadly OOP pattern) of encapsulation. > > I'd add, for newcomers, that the fact that you declared fields "final" > has nothing to do with your AbstractEvent. -- You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.
