如果您删除对父对象的所有引用,则不需要删除其子对象或对子对象的侦听器(假设没有对子对象的外部引用)。
标记清除垃圾回收器通过遍历对象图从最顶层的对象(即舞台)开始工作。将所有路径剪除到图的一部分中,并且整个子图将有资格收集,而不管子图之间有任何引用。
首先,让我们考虑只是一个显示列表层次结构,而不事件:
var clip:Sprite = new Sprite();
addChild(clip);
var clip2 = new Sprite();
clip.addChild(clip2);
// cleanup
removeChild(clip);
clip = null;
clip2 = null;
内孩子CLIP2会被垃圾收集,即使我们没有通过clip.removeChild(clip2)
从其父将其删除。由于我们删除了所有对父代clip
的引用和明确的clip2
引用,因此无法访问它,因此它将被垃圾收集。因此,没有必要removeChild
后代剪辑。只要确保你清除任何外部引用(在这种情况下,clip2
)。
现在让我们想象一些事件:
var clip:Sprite = new Sprite();
addChild(clip);
clip.addEventListener(MouseEvent.CLICK, someListener);
var clip2:Sprite = new Sprite();
clip.addChild(clip2);
clip2.addEventListener(MouseEvent.CLICK, someOtherListener);
// cleanup -- the same!
removeChild(clip);
clip = null;
clip2 = null;
你可能会认为你必须删除事件侦听器,但它实际上是没有必要的。 addEventListener创建从调度程序到侦听器的引用。也就是说,将侦听器添加到子对象不会阻止其垃圾收集。在这种情况下,addEventListener
将剪辑引用到root,将clip2引用到root。发生垃圾回收时,即使该侦听器在那里,标记也不能从根节点跳转到剪辑。参考是其他方向,从剪辑到根!所以对象仍然会被垃圾收集。因此,在这种情况下,不必删除监听器。也就是说,如果你不确定,这并不会伤害你。
的唯一途径听众可以防止垃圾回收是,如果一个孩子夹在听父剪辑:
// from inside clip
root.addEventListener(MouseEvent.CLICK, someHandler);
此侦听器创建一个从根参考夹,所以您必须删除引用或使用弱引用。既然你使用的是弱引用,你也不必担心。
确实需要跟踪很多事情,并且很容易犯错,所以最好是在您完成对话时删除听众。如果你删除它们,你将永远安全。这对于Flash为您调度的奇怪本地事件非常重要,如Event.ENTER_FRAME和KeyboardEvent.KEY_DOWN,但不是因为垃圾回收问题:即使剪辑没有引用并且有资格收集,它仍会继续接收ENTER_FRAME事件,直到垃圾收集器实际运行在未来的某个不确定点。所以你应该总是删除ENTER_FRAME监听器。
但是在使用简单MouseEvent的小对象图的情况下,即使您不打扰删除侦听器,您也可以。他们不会伤害任何东西,当剪辑从显示列表中删除时,他们将不再被分派。你可以只用removeChild
父剪辑并完成它。
如果您想查看正在发生的事情,在Flash Builder,FlashDevelop或FDT中使用Profiler工具查看内存使用情况会很有帮助。如果您想测试这些想法,您也可以使用System.gc();
调用来强制GC以调试模式运行。
你必须删除所有孩子的所有听众。即使父级设置为空,侦听器仍然存在。 – jpea 2011-03-25 18:07:18