如何处理未使用的 GWT 小部件
How to dispose of unused GWT Widgets
我正在开发的 GWT+GXT UI 模块使用面板之间的切换来实现不同类型的视图。非常简单的例子:
mainPanel.add(successPanel);
或
mainPanel.add(errorPanel);
我注意到,如果 errorPanel 从未被使用(附加),它就永远不会被丢弃。
我知道将 UI 元素添加到 DOM 并切换可见性应该会获得相同的结果并提供适当的 GC,但是,重构所有内容以执行此操作可能会引入许多其他问题.
我试过以下方法:
- 将未使用的元素附加到 RootPanel,然后调用 widget.removeFromParent()。
- 将未使用的元素添加到活动的 DOM 元素中,就在该活动元素被处理之前
- 正在调用 DOM.setEventListener(widget.getElement(), null).
- 制作一个助手 class 提供 removeMethod 而不管附件状态:
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 这些方法可靠地工作。有什么方法可以将未使用的小部件标记为不需要,并让 GWT 处理所有处理,包括其子部件?
与我的问题有点相关,除了 "roll-your-own" 跟踪器之外,有什么方法可以找出哪些 widgets/classes 没有被处理掉?
GWT 小部件没有 "dispose" - 只有 attach/detach。如果小部件已分离(或从未附加),那么一旦您没有对它的引用,正常的垃圾收集就会工作。
如果您将它保留在 "attached" 模式,但实际上删除了对它的所有引用(手动将其从 DOM 中删除,或者手动触发附加而不实际将其放入 DOM, 等), 它会在 一些 浏览器(古老的 firefox, IE6-9 或 10, 等) 中泄漏内存.
您执行附加和分离步骤与从一开始就不附加它的效果相同。您的泄漏在其他地方,而不是在 GWT Widget 的生命周期中。 GWT 中没有"dispose"——只要不实际附加,普通的GC 就够了。
我正在开发的 GWT+GXT UI 模块使用面板之间的切换来实现不同类型的视图。非常简单的例子:
mainPanel.add(successPanel);
或
mainPanel.add(errorPanel);
我注意到,如果 errorPanel 从未被使用(附加),它就永远不会被丢弃。
我知道将 UI 元素添加到 DOM 并切换可见性应该会获得相同的结果并提供适当的 GC,但是,重构所有内容以执行此操作可能会引入许多其他问题.
我试过以下方法:
- 将未使用的元素附加到 RootPanel,然后调用 widget.removeFromParent()。
- 将未使用的元素添加到活动的 DOM 元素中,就在该活动元素被处理之前
- 正在调用 DOM.setEventListener(widget.getElement(), null).
- 制作一个助手 class 提供 removeMethod 而不管附件状态:
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 这些方法可靠地工作。有什么方法可以将未使用的小部件标记为不需要,并让 GWT 处理所有处理,包括其子部件?
与我的问题有点相关,除了 "roll-your-own" 跟踪器之外,有什么方法可以找出哪些 widgets/classes 没有被处理掉?
GWT 小部件没有 "dispose" - 只有 attach/detach。如果小部件已分离(或从未附加),那么一旦您没有对它的引用,正常的垃圾收集就会工作。
如果您将它保留在 "attached" 模式,但实际上删除了对它的所有引用(手动将其从 DOM 中删除,或者手动触发附加而不实际将其放入 DOM, 等), 它会在 一些 浏览器(古老的 firefox, IE6-9 或 10, 等) 中泄漏内存.
您执行附加和分离步骤与从一开始就不附加它的效果相同。您的泄漏在其他地方,而不是在 GWT Widget 的生命周期中。 GWT 中没有"dispose"——只要不实际附加,普通的GC 就够了。