A GWT+GXT UI module I'm working on uses switching between panels in order to achieve different kind of views. Very simplified example:
mainPanel.add(successPanel);
OR
mainPanel.add(errorPanel);
I've noticed that if errorPanel never gets used (attached) it never gets disposed.
I know that adding both UI elements to the DOM and toggling visibility should achieve the same result and provide proper GC, but, refactoring everything to do that might introduce a lot of other issues.
I've tried the following methods:
public static void removeWidget(Widget w) {
if (w.getParent() == null) {
RootPanel.get().add(w);
if (RootPanel.isInDetachList(w)) {
RootPanel.detachNow(w);
} else {
try {
// onUnload() gets called *before* everything else (the opposite of
// onLoad()).
w.onUnload();
AttachEvent.fire(w, false);
} catch (Exception e) {
// ??? throws "Should only call onDetach when the widget is attached to the browser's document"
} finally {
// Put this in a finally, just in case onUnload throws an exception.
try {
w.doDetachChildren();
} catch (Exception e) {
// ???
} finally {
// Put this in a finally, in case doDetachChildren throws an exception.
DOM.setEventListener(w.getElement(), null);
//w.attached = false; // ??
}
}
}
} else if (w instanceof HasWidgets) {
((HasWidgets) w).remove(w);
} else if (w != null) {
throw new IllegalStateException("This widget's parent does not implement HasWidgets");
}
}
None of these methods worked reliably. Is there any way to mark an unused widget as not needed and have GWT handle all the disposing, including its children?
Somehow related to my question, is there any way to figure out which widgets/classes are not being disposed of, short of a "roll-your-own" tracker?
There is no "dispose" for GWT Widget - there is only attach/detach. If the widget is detached (or never attached), then normal garbage collection will work once you have no references to it.
If you leave it in "attached" mode, but actually remove all references to it (manually removing it from the DOM, or manually triggering attach without actually putting it in the DOM, etc), it will leak memory in some browsers (ancient firefox, IE6-9 or 10, etc).
Your steps of going through attach and detach have the same effect as never attaching it to begin with. Your leak is somewhere else, not in GWT Widget's lifecycle. There is no "dispose" in GWT - as long as it isn't actually attached, normal GC is enough.