如何在使用FileRerence后释放内存



参见[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;
}

这个问题是上述所有问题的综合。

  1. 您确实需要手动删除事件侦听器。虽然可以使用弱引用,但最好养成跟踪已注册的侦听器并始终正确地注销它们的习惯。通过这种方式,您可以更好地避免您没有预料到或没有考虑到的内存泄漏(不完全是内存泄漏,但具有类似的效果)。

  2. 您正在循环中创建事件侦听器,并重用相同的函数来处理所有事件。如果这样做,您必须以某种方式获得对原始加载器的引用,并从中删除事件侦听器。我不知道你是如何尝试合并Zhafur的答案,但如果你为每个新文件重复使用文件引用,这将是它仍然不起作用的原因。也许你可以用你现有的代码更新上面的例子,这样我们就可以进一步评论了。

  3. 你不应该强制gc(垃圾收集器),如果你需要这样做,你有其他地方的问题,你应该解决而不是san。在提及。强制GC是一种很好的方式,可以看到你创建了太多的对象太快,如果你看到你的内存使用在强制GC之后下降,你可能已经这样做了,应该重写你的代码,以更有效地使用new。

根据你所消耗的内存量来判断,你要么创建了大量的小文件,要么创建了一些非常大的文件,也许你可以告诉我们更多关于这个的信息。

相关内容

  • 没有找到相关文章

最新更新