所有
我是否创建了一个sprite,并且该sprite包含许多子sprite(它们本身也包含子sprite),我是否需要担心垃圾收集所有内容,或者只是父级sprite?如果孩子或孙子精灵有听众怎么办?
例如,假设我有一个类(Sprite的子类)在应用程序中创建一个屏幕。
该屏幕包含许多用于屏幕上所有UI功能的精灵(例如,按钮,下拉菜单,文本字段等)。许多精灵都有事件监听器。
所以,在我的申请中,我有这个:
var myscreen:MyScreenClass = new MyScreenClass();
this.addChild(myscreen);
稍后,当用户完成该屏幕后,我将其删除:
this.removeChild(myscreen);
myscreen = null;
这就是我需要做的吗?或者,我是否需要递归通过myscreen,删除所有它的子Sprite和事件监听器?
换句话说,如果你是父母的GC,那么所有的孩子,孙子孙女,曾孙子等也是GC的吗?
(对于它的价值,我在我的事件监听器中使用弱引用......)
提前致谢!
答案 0 :(得分:10)
如果删除对父对象的所有引用,则不必删除子对象或子对象的侦听器,假设没有对子对象的外部引用。
标记清除垃圾收集器通过遍历对象图来工作,从最顶层的对象(即,舞台)开始。剪掉图形的一部分的所有路径,并且整个子图将有资格收集,无论子图本身有任何引用。
首先,让我们考虑一下没有事件的显示列表层次结构:
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
从剪辑到根,并将clip2引用到root。当垃圾收集发生时,标记不能从根跳到剪辑,即使该监听器在那里。从剪辑到根,参考是其他方向!所以对象仍将被垃圾收集。因此,在这种情况下没有必要删除侦听器。也就是说,如果你不确定,这样做并没有什么坏处。
侦听器可以阻止垃圾回收的唯一方法是子剪辑正在侦听父剪辑:
// from inside clip
root.addEventListener(MouseEvent.CLICK, someHandler);
此侦听器创建从root到clip的引用,因此您必须删除该引用或使用弱引用。由于您使用的是弱引用,因此您也不必担心这一点。
确实有很多需要跟踪的内容,并且很容易出错,所以最好在完成后删除侦听器。如果你删除它们,你将永远是安全的。 Flash为您调度的奇怪的本机事件非常重要,例如Event.ENTER_FRAME和KeyboardEvent.KEY_DOWN,但不是因为垃圾收集问题:即使剪辑没有引用且有资格收集,它也会继续收到ENTER_FRAME事件,直到垃圾收集器实际上在未来的某个不确定点运行。所以你应该总是删除ENTER_FRAME监听器。
但是对于带有简单MouseEvents的小对象图,即使您不打算删除侦听器,也可以。它们不会伤害任何东西,当剪辑从显示列表中删除时,它们将不再被分派。您只需removeChild
父剪辑即可完成。
如果您想查看正在发生的事情,使用Flash Builder,FlashDevelop或FDT中的探查器工具来查看内存使用情况会很有帮助。如果要测试这些想法,也可以使用System.gc();
调用强制GC在调试模式下运行。
答案 1 :(得分:4)
是的,您甚至需要从子节点中删除所有侦听器
AS3 quick and efficient way of removing children and listeners and discarding the parent
Why does AS3 not use weak references by default? (in event listeners)
编辑:
特别阅读: http://gingerbinger.com/2010/07/actionscript-3-0-events-the-myth-of-useweakreference/
http://gskinner.com/blog/archives/2006/06/as3_resource_ma.html