参见[Solution]
FileReference.load();
没有卸载功能,就像new Loader ().unload();
一样。
必须是一个"BUG"从Flash或FileReference
需要改进,在新版本中输入添加这样的功能:FileReference.unload();
还是我错了,存在解决方案?
我试图将"NULL"设置为FileReference
类型的变量,但显然这不适用于Flash与GC(垃圾收集器)一起工作,但这不是问题的焦点。
问题是,大量的内存加载多个文件与new FileReferenceList
是必要的,但我不能释放内存后的进程。
使用FileRerence
后如何释放内存?
查看我的代码:
文件main
package {
import com.mainpackage.LoaderTestCase;
import flash.net.FileReferenceList;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.events.Event;
import flash.display.MovieClip;
public class Main extends MovieClip {
private var listFiles:Array;
private var allTypes:Array;
private var fileRef:FileReferenceList;
private var test:int;
public function Main()
{
test = 0;
listFiles = [];
allTypes = [];
fileRef = new FileReferenceList();
fileRef.addEventListener(Event.SELECT, select);
fileRef.browse(allTypes);
}
private function select(e:Event):void
{
listFiles = fileRef.fileList;
for(var i:uint=0, j:uint=listFiles.length; i<j; i++)
{
insert(i);
}
}
private function insert(c:int):void
{
var fire:LoaderTestCase = new LoaderTestCase(listFiles[c]);
fire.destroy(function():void
{
//Delete LoaderTestCase after timeout ???
fire = null;
test++;
if(test>=listFiles.length) {//Remove FileReference
fileRef.removeEventListener(Event.SELECT, select);
fileRef = null;
for(var i:uint=0, j:uint=listFiles.length; i<j; i++) {
listFiles[i] = null;
}
listFiles = null;
trace("Clear memory");
}
});
}
}
}
LoaderTestCase.as
package com.mainpackage
{
import flash.net.FileReference;
import flash.events.Event;
import flash.display.Loader;
public class LoaderTestCase
{
private var file:FileReference;
private var loader:Loader;
private var callback:Function;
public function LoaderTestCase(e:FileReference)
{
file = e;
trace("OPEN: " + file.name);
file.addEventListener(Event.COMPLETE, loadFile);
file.load();
e = null;
}
public function loadFile(e:Event):void
{
file.removeEventListener(Event.COMPLETE, loadFile);
trace("LOAD: " + file.name);
file = null;
e = null;
callback();
}
public function destroy(a:Function):void
{
callback = a;
}
}
}
在清空侦听对象之前删除事件侦听器。
当对象被垃圾收集时,可以使用弱引用来删除侦听器。
object.addEventListener( ......, ......., false, 0, true );
例如,在LoadFile函数中:
...
LoadFile(file);
}
});
...
应: ...
LoadFile(file);
}
}, false, 0, true );
...
否则你必须手动删除它们。
要做到这一点,您需要将事件处理程序移动到新的命名函数中。
还需要一个数组来存储对侦听器和侦听对象的引用,以便能够在侦听器不再需要之后和在侦听对象为空之前删除侦听器。
请注意:
当您在测试它并观察当前内存使用情况时,请确保在您觉得内存使用现在应该下降但没有时强制执行Garbage Collector。
GC在它想要的时候启动,而不一定是在某些东西在卸载时被空了之后。
要清楚,我只是在谈论开发/测试期间强制GC。
我达到了我的目标,如果我这样做了FileReferenceList.fileList[5] = null;
(当"第六个文件"没有被更多地使用时)闪存立即释放这个特定的FileReference
。
换句话说:
This not work:
private var file:FileReference;
...
file = FileReferenceList.fileList[5];
...
file = null;
但这有效:
FileReferenceList.fileList[5] = null;
适用于所有的Desktop/Plugins/PepperFlash。
见工作代码:
package {
import flash.net.FileReferenceList;
import flash.net.FileReference;
import flash.net.FileFilter;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.display.Sprite;
public class Main extends Sprite
{
private var listFiles:Array;
private var allTypes:Array;
private var fileRef:FileReferenceList;
private var tmpFile:FileReference;
private var i:uint=0;
private var j:uint=0;
private var timer:uint;
private var imageTypes:FileFilter;
private var enable:Boolean;
public function Main()
{
imageTypes = new FileFilter(
"Images (*.JPG;*.JPEG;*.JPE;)", "*.jpg; *.jpeg; *.jpe;"
);
listFiles = [];
allTypes = [imageTypes];
eventBrowse(true);
}
private function eventBrowse(a:Boolean):void
{
enable = a;
if(a===true) {
stage.addEventListener(MouseEvent.CLICK, browse);
fileRef = new FileReferenceList();
fileRef.addEventListener(Event.SELECT, select);
} else {
fileRef.removeEventListener(Event.SELECT, select);
fileRef = null;
stage.removeEventListener(MouseEvent.CLICK, browse);
}
}
private function browse(e:MouseEvent):void
{
if(enable===true) {
fileRef.browse(allTypes);
}
}
private function select(e:Event):void
{
listFiles = fileRef.fileList;
eventBrowse(false);
i=0;
j=listFiles.length;
if(j>0) {
loadNextFile();
}
}
private function loadNextFile():void
{
if(!(i<j)) {
listFiles = null;
trace("Free memory???");
trace("--------------");
trace("listFiles:"+ listFiles);
trace("allTypes:" + allTypes);
trace("fileRef:" + fileRef);
trace("tmpFile:" + tmpFile);
trace("i:" + i);
trace("j:" + j);
trace("timer:" + timer);
trace("--------------");
eventBrowse(true);
return;
}
tmpFile = listFiles[i];
trace("Initiate load:" + tmpFile.name);
tmpFile.addEventListener(Event.COMPLETE, loadedFile);
tmpFile.load();
}
private function loadedFile(f:Event):void
{
trace(listFiles);
trace("Finished load:" + tmpFile.name);
tmpFile.removeEventListener(Event.COMPLETE, loadedFile);
tmpFile = null;
listFiles[i] = null;
i++;
loadNextFile();
}
}
}
即使对一个对象的每个引用都为null,它也不会立即从内存中删除。您还必须删除事件侦听器。另外,永远不要使用"未命名"的函数…当事件调用未命名的函数时,很难删除侦听器。所以创建一个新函数,并调用它。例如:
test.contentLoaderInfo.addEventListener(Event.COMPLETE, contentLoaderInfoComplete);
...
function contentLoaderInfoComplete(e:Event){
test.contentLoaderInfo.removeEventListener(Event.COMPLETE, contentLoaderInfoComplete);
test.unload();
test = null;
}
这个问题是上述所有问题的综合。
-
您确实需要手动删除事件侦听器。虽然可以使用弱引用,但最好养成跟踪已注册的侦听器并始终正确地注销它们的习惯。通过这种方式,您可以更好地避免您没有预料到或没有考虑到的内存泄漏(不完全是内存泄漏,但具有类似的效果)。
-
您正在循环中创建事件侦听器,并重用相同的函数来处理所有事件。如果这样做,您必须以某种方式获得对原始加载器的引用,并从中删除事件侦听器。我不知道你是如何尝试合并Zhafur的答案,但如果你为每个新文件重复使用文件引用,这将是它仍然不起作用的原因。也许你可以用你现有的代码更新上面的例子,这样我们就可以进一步评论了。
-
你不应该强制gc(垃圾收集器),如果你需要这样做,你有其他地方的问题,你应该解决而不是san。在提及。强制GC是一种很好的方式,可以看到你创建了太多的对象太快,如果你看到你的内存使用在强制GC之后下降,你可能已经这样做了,应该重写你的代码,以更有效地使用new。
根据你所消耗的内存量来判断,你要么创建了大量的小文件,要么创建了一些非常大的文件,也许你可以告诉我们更多关于这个的信息。