Flash 此代码会导致内存泄漏吗?
这会导致内存泄漏吗Flash 此代码会导致内存泄漏吗?,flash,actionscript-3,Flash,Actionscript 3,这会导致内存泄漏吗 var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP for ( var i=0 ; i< 1000 ; i++) { mc = new MovieClip() ; mc.addEventListener( MouseEvent.CLICK , onClick) ; } var-mc:MovieClip// 更新,回答正确 我最初的回答是错误的,我真诚地道歉。我将保留我所有屈尊的评论
var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP
for ( var i=0 ; i< 1000 ; i++)
{
mc = new MovieClip() ;
mc.addEventListener( MouseEvent.CLICK , onClick) ;
}
var-mc:MovieClip// 更新,回答正确
我最初的回答是错误的,我真诚地道歉。我将保留我所有屈尊的评论和信息,以使羞愧永远提醒我不要再相信Adobe所说的任何话。目前的文件表明:
“如果不再需要事件侦听器,请通过调用removeEventListener()将其删除,否则可能会导致内存问题。事件侦听器不会自动从内存中删除,因为只要调度对象存在,垃圾收集器就不会删除侦听器。”(除非useWeakReference参数设置为true)。”
请注意,事件侦听器是垃圾收集的,无论是否存在弱引用,只要首先删除分派对象。因此,在这两种情况下,它们都不会导致内存泄漏。我要求OP取消检查我的答案是否正确,并将信用/正确答案+upvoces赋予@Malyngo
原始(错误)答案和(错误)信息如下
两者都会。绑定事件侦听器会创建对原始对象的强引用,因此垃圾收集器不会清理它。您需要显式删除事件侦听器或将其指定为弱引用,这应该是addEventListener的参数之一
对于那些认为侦听器不会阻止其他对象被垃圾收集的人来说
文章摘要:
"假设我们的玩家死了,我们希望他被清理干净。但是,事件侦听器创建了一个从stage到玩家的引用。stage是最上面的显示对象,总是可以访问的。因此,当mark sweep进程运行时,此事件侦听器允许垃圾收集器从stage跳到我们的玩家对象even如果我们已清除所有其他引用并将其从显示列表中删除。”
因此,至少有一种情况下,事件侦听器单独强绑定可以阻止对象被收集。
最佳做法解决方案:
1) 将其从显示列表中删除。
2) 如果是电影剪辑,告诉它停止()
3) 删除对象已创建的所有事件侦听器。
4) 通过将父对象中的所有引用设置为null来清除它们。
再次更新
内存泄漏不一定意味着您会看到应用程序的内存不断增长。内存泄漏也可以简单地描述在应用程序生命周期内分配并持续的内存,而应用程序应该回收。类似于此的测试代码不太容易检测到。但要在一个小时内使其发生N次游戏,我保证它会显示出来。我曾经写过一个加密算法,我也遇到过同样的情况。过了一段时间,我的应用程序开始以每秒10帧或更少的速度运行,因为虚拟机已经消耗了大量内存,它实际上已经不再使用了,但它仍然在管理它。这两个例子都是一样的,就像actionscript一样基于没有块作用域的ecmascript 3
编辑:让我更具体一点:ActionScript中没有块作用域,但有函数作用域
与内存泄漏一样,对象将保留在内存中。您的1000 Movieclips将引用onClick函数,而不是相反。
所以,如果你的问题是你的1000部电影是否会获得GCD:如果他们没有任何其他参考,他们最终会获得GCD
someObjectBelowIntheDisplayList.addEventListener(MouseEvent.CLICK, stage.onClick)
另一方面,movieclips中对onClick函数的引用将使其保持活动状态(以及它可能属于的对象)。如果这些mc有任何其他引用将使其保持活动状态
以下代码:
mc.addEventListener(MouseEvent.CLICK , function(ev:Event):void{ trace("I am only a poor anonymous function"); }, false, 0, true);
import flash.display.MovieClip;
import flash.events.Event;
var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP
function enterframe(ev:Event):void
{
for ( var i=0 ; i< 1000 ; i++)
{
mc = new MovieClip() ;
mc.onClick = function(ev:Event){};
// Use one of the following lines, comment out the other one
//mc.addEventListener( MouseEvent.CLICK , onClick) ; // no memory leak
stage.addEventListener(MouseEvent.CLICK, mc.onClick); // memory will rise up and up
}
}
this.addEventListener(Event.ENTER_FRAME, enterframe);
function onClick(ev:Event):void
{
}
将很快让您的侦听器函数GCed,因为它没有任何强引用
someObjectBelowIntheDisplayList.addEventListener(MouseEvent.CLICK, stage.onClick)
如果将Eventlistener添加到舞台,则将useWeakReference设置为true可能非常相关
stage.addEventListener(MouseEvent.CLICK, someObjectBelowIntheDisplayList.listenerFunction);
上面的代码将使带有侦听器函数的对象保持活动状态,即使它没有其他引用
someObjectBelowIntheDisplayList.addEventListener(MouseEvent.CLICK, stage.onClick)
上述代码不会使您的someObjectBelowIntheDisplayList保持活动状态。它有一个对stage的引用,但stage没有对someObjectBelowIntheDisplayList的引用
编辑:请尝试以下代码:
mc.addEventListener(MouseEvent.CLICK , function(ev:Event):void{ trace("I am only a poor anonymous function"); }, false, 0, true);
import flash.display.MovieClip;
import flash.events.Event;
var mc:MovieClip ; //<<<<<<< OUTSIDE LOOP
function enterframe(ev:Event):void
{
for ( var i=0 ; i< 1000 ; i++)
{
mc = new MovieClip() ;
mc.onClick = function(ev:Event){};
// Use one of the following lines, comment out the other one
//mc.addEventListener( MouseEvent.CLICK , onClick) ; // no memory leak
stage.addEventListener(MouseEvent.CLICK, mc.onClick); // memory will rise up and up
}
}
this.addEventListener(Event.ENTER_FRAME, enterframe);
function onClick(ev:Event):void
{
}
导入flash.display.MovieClip;
导入flash.events.Event;
var mc:MovieClip;//“没有块作用域“这是假的。如果你的意思是说作用域与内存分配和去分配无关,那是另一回事,但简单地说没有块作用域本身是错误的。我实际上会说这是正确的,只要你不把函数算作块作用域,而把它当作它自己的作用域。(这在技术上也是正确的)。我想说的是JNissi,AS3使用变量提升,所以在循环内部或外部声明变量具有相同的效果;)在这一点上,两者都不会导致内存泄漏,因为您可能需要所有1000个movieclips都可以单击。只有当您处理完movieclips并希望将其从内存中删除时,事件侦听器问题才会出现。Ascention的答案是正确的,但“将”这个词很重要。在座的各位,我站在正确的立场上。我再也不会相信adobe文档了。请参阅我的最新答案。我目前的答案是错误的。我上面提供的测试代码经常在每一帧上创建1000个Movieclips。如果出现内存泄漏,内存消耗必须增加,因为不会收集所有这些对象。但事实确实如此。通过将Movieclips作为侦听器添加到舞台,存在内存泄漏。引用总是从调度器到侦听器,而不是相反。因此,如果不再有对dispatcher的引用,它将被销毁,不管它可能有多少个侦听器