سؤال

I am working in a large application I inherited, and am running into some best practices issues.

Every time a user navigates to our Customer Edit page, a new presenter is created, and a view is set. There is a main presenter for the customer edit, and a main view. There are also sub views within the main view that are used by sub presenters of the main presenter. Within the sub presenters I register event handlers on the event bus.

The issue I'm having is that when a navigates to the contact editor a second time, the presenter is created again, and those events are registered again. Now when an event occurs, it is handled twice, once for each presenter instance.

The presenter isn't held onto by a variable, but the sub view is referenced by the main view. Could It be that this reference in the view is keeping the event handlers from being removed? I was under the impression that event handlers will be removed if that object was garbage collected. If this is not the case, should I be un-registering these event handlers from the event bus?

Update: The presenters are not being garbage collected. If I can modify the code to remove all references to those presenters when they are no longer needed, will they be collected, and therefore will the event handlers be removed?

هل كانت مفيدة؟

المحلول 2

The event handlers are separate object instances that are set and stored against some kind of collection inside the EventBus. Your presenter just creates them and passes them to the EventBus, so the handlers are still referenced beyond the lifetime of the presenter (and that's why they keep running). The presenters are probably not being garbage collected because the handlers may still reference them or their fields.

Having a new presenter created adds the handlers again every time as you've detected, so the solution is to either clear the existing handlers prior to instantiating the new presenter or to keep track of them and not add new handlers when they're already added.

The approach I take is to reuse the screen-level View/Presenter instances and reset their state when re-entering. This also helps with performance. The presenters also keep track of the HandlerRegistration instances for all handlers they add to the EventBus.

I wasn't aware of ResettableEventBus that Colin mentions, but that sounds like a good solution as well.

نصائح أخرى

The ResettableEventBus is specifically designed for this - instead of giving the Presenter a global event bus, you wrap up that event bus in the Resettable version. Then, when that presenter is shut down, whoever gave it that event bus resets it, thus cleaning up all handlers that it may have added.

This is how Activities in GWT's Activity/Place framework are managed to prevent them from leaking.

Another option - give each Presenter a method like 'stop()' or 'release()', indicating that it is top to go, and it should mop up after itself - cancel in-progress RPC calls, remove dialog boxes, cancel event handlers. And as above, the Activity api has a method to indicate that it is about to stop, and that it has stopped and should clean up.

Providing both makes it easy to not make mistakes with the global event bus, and still giving a hook for more fine grained issues (long running RPC calls), but the problem can be solved with either solution.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top