in gwt Panel.clear() method clears all child widgets. Does that mean all even handlers associated with those child widgets will be removed or garbage collected as well?
Yes, it will (at least if the child widget cleaned their reference to application-transversal objects like the eventBus and don't hold circular references).
As per this documentation
The core GWT widget
system has a very specific event-handling system that makes it
impossible to trigger a leak.
It will also work in IE, as long as you
don't go straight to JSNI and hook up event handlers yourself (using
things like Event.sinkEvents() is just fine).
Calling Widget.removeEventListener() or
HandlerRegistration.removeHandler() is never necessary (or useful)
for any reason other than that you want to stop
receiving events (this is one reason we tucked removeHandler() into
HandlerRegistration -- most people never need to call it).
and this blog post.
However, removeHandler is required to avoid application-level, java-esque memory
leaks.
If you have a “global” event source, like an always-visible navigation
bar widget or an application-wide EventBus, and you have a transient
event listener, like a presenter listening for events, the presenter’s
event handler will keep it from being garbage collected until the
EventBus is also garbage collected.
So don't worry about widgets or #UIHandler. Just clear the tab and it'll work.
No it will not. You have to call removeHandler(). (eventually)
In this doumcnetation:
>
2 . removeHandler is required to avoid application-level memory leaks.
If you have a “global” event source, like an always-visible navigation
bar widget or an application-wide EventBus, and you have a transient
event listener, like a presenter listening for events, the presenter’s
event handler will keep it from being garbage collected until the
EventBus is also garbage collected.
Related
what if I do a viewer.refresh() at the same time I close the tree viewer on the UI.
What will happen and how I can handle this situation?
This shouldn't happen in the same time, as UI events (such as close or refresh) are inherently single-threaded - they can happen only one after the other (unless you call refresh inside the dispose, or dispose during refresh, however both of them are hard to justify as normal steps)..
If your question was motivated by an SWT error of widget is disposed, then most likely you have disposed of something previously, but nonetheless called its refresh method - I would look it at that way.
Maybe you have more than one listener and trees around? I would advice to add a disposeListener to the tree and put a breakpoint into it. Then you see when it gets disposed.
I'm currently working on a GWT application and I'm still a little fuzzy on how it all fits together (the joy of having to make changes without first coming to an understanding of the whole framework, although that might be difficult anyway).
We have a few Activities that all correspond to parts of the UI (e.g. main content, a toolbar and a list of things). I'm not really sure whether that's even how Activities are intended but I guess I can't really change that easily now. My problem now is that the list of things holds state (the current selection) that the main content also needs and in a way the toolbar too (at least the toolbar currently has it – I'm beyond asking).
But what would actually be an appropriate place to store that? I guess coupling the actual view implementations together and storing the selection only in the list isn't such a bright idea.
I see two main solutions here:
keep the state within each activity and keep them synchronized through events (on the EventBus). That is: the "list of things" has a current selection, main view has one too, so does the toolbar; and each time that value changes, the activity that's making the change fires an event on the event bus so that the other activities can update their state, so that all activities have the same value in their own state.
use a singleton object (if you're using GIN and dependency injection, simply annotate the object with #Singleton and inject it in all the activities) to keep the state at a central place. The activities register event handlers on the state holder object to be notified when it changes. That is, each time an activity calls setCurrentSelection (for example), an event is fired (for example a ValueChangeEvent), and because all activities listen for it, they can update their view or whatever depending on the new value. You can choose to either dispatch the event on the event bus (similar to the PlaceController) or have the state holder implement HasValueChangeHandlers. Just make sure to unregister the handlers when the activities stop to avoid memory leaks (dispatching on the event bus makes it easier: simply register the handlers on the bus passed as argument to the start method and they'll be unregistered automatically when the activity stops, and you don't even have to think about it).
Actually, PlaceController is a good example of such shared state (the current place).
I have two widgets listening for a MouseOutEvent. Problem is that sometimes this events does not get called on both of the widgeth even if you mouse out of them.
No error is thrown and this is extremely hard to debug.
My understanding is that this event is fired by a browser, so I don't understand why this is not happening. I am registering this event to the widget itself.
Any suggestions will be a great help.
Thanks
Sounds like you might have used addHandler to register to your MouseOverHandler. Widget has two methods for adding event handlers, addDomHandler and addHandler. The first is meant to be used for DomEvents, e.g. MouseOutEvents. It sinks the event on the widget, which means that your listener will get notified (this is only necessary for DomEvents). Those events might not get fired if you do not use addDomHandler to register your handler.
How to throw a View event, such click on a button, in view's activity? View doesn't know activity eventBus..
I miss something? I'm using 2.3 sdk
I think the best option is to keep a reference to the Activity in the view and then forward the event to the Activity, which can then use the EventBus in it's own method.
There is a small example on this page:
http://code.google.com/intl/sv-SE/webtoolkit/doc/latest/DevGuideMvpActivitiesAndPlaces.html
But basically, I usually use #UiHandler to handle the ClickEvent, and then invoke a method in the Activity. In the Activity I then perform the action that uses the EventBus, RPC, or so. I know some people prefer handling the event directly in the Activity but to me this seems like a nicer separation of concern and keeps the View nicely "stupid".
An example:
Button says something like "Select active customer"
View handles ClickEvent for the button, invokes presenter.customerSelected(...)
Activity has customerSelected method and creates a ActiveCustomerSelectedEvent, which is sends on the EventBus.
i'm new to GWT2.1's Places and Activities.
I'm using the same ActivityMapper as example below and getting laggy button clicks after just a few navigations.
The MVP architecture I'm using has the Presenter create listeners and define the View interface, but View objects are singletons.
Is my problem with lag due to all the listeners building up exponentially? Should I change it so that the View creates all the listeners instead? Or should I try unbinding instead?
E.g. in the GWT2.1 example here a new Activity is created every time getActivity(Place) is called.
public Activity getActivity(Place place) {
if (place instanceof HelloPlace)
return new HelloActivity((HelloPlace) place, clientFactory);
else if (place instanceof GoodbyePlace)
return new GoodbyeActivity((GoodbyePlace) place, clientFactory);
return null;
}
The view here adds event handlers to its widgets. It later calls its presenter when appropiate. I don't think that unbindinding the events would free up much memory or speed up the browser's event queue.
I believe you should further investigate if the actual button click is slow, or if it's the creation of Activities happening upon the event, or whatever else.
In the end I changed the MVP architecture to the same as the example here with View defining Activity and ViewImpl containing the UI Handlers. Since the Activities no longer contain handlers and the ViewImpls are singletons the problem goes away.