利用Loader的unload()方法,可以删除Loader同加载对象之间的关系。调用Loader之后,Loader的子对象被解除显示列表的依附关系,但被加载对象依然实际存在。无论是否有其他对象保留对其的引用,被加载对象都不会被回收。如果不谨慎处理这种机制,很容易会造成内存Bug和资源浪费。为了避免这样的问题,应尽量避免直接使用打开的图像文件。而是将打开的文件写入新的位图副本,并关闭Loader对象,释放位图缓存。
下面的代码中,创建了一个新的BitmapData对象“mybd”,并将Loader加载的图像绘入该位图。保留“mybd”以供其他部分使用。本段代码执行后,在屏幕上最终显示的位图是利用的“mybd”创建的。由于Bitmap不是一个可以接受用户交互操作的类,所以需要将其装入一个Sprite对象,并利用该Sprite对象接受用户交互消息。
var imgLoader:Loader=new Loader();
imgLoader.load(new URLRequest("imgdata/img.gif"));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,loadok);
//创建侦听鼠标滚轮事件的显示对象
var box:Sprite=new Sprite();
box.addEventListener(MouseEvent.MOUSE_WHEEL,mclick);
stage.addChild(box);
//加载完毕后,调用此侦听器函数
function loadok(leo:Event):void {
//创建临时Loader
var temploader:Loader=leo.target.loader as Loader;
//载入位图
var mybd:BitmapData;
mybd=new BitmapData(temploader.width,temploader.height,false);
mybd.draw(temploader);
var ibitmap:Bitmap;
ibitmap=new Bitmap(mybd);
box.addChild(ibitmap);
//以下代码尝试释放位图内存
var bt:BitmapData=leo.target.content.bitmapData;
temploader.unload();
bt.dispose();
trace(bt.width);
}
//鼠标滚轮响应函数
function mclick(eve:MouseEvent):void {
eve.target.alpha+=(eve.delta/500);
if (eve.target.alpha<0) {
eve.target.alpha=0;
} else if (eve.target.alpha>1) {
eve.target.alpha=1;
}
}
目前的FlashPlayer对加载对象的物理文件,存在过度发的保护。开发者在代码中使用内存释放,不能真正的解除对文件的访问。即使对位图调用了dispose()方法,依然不能修改外部的图像文件。被加载的文件将保持打开状态,不能被修改。这种情况会造成严重的后果。如果开发一个网上相册程序,当用户访问SWF是,网站管理员就不能替换和修改打开的图像文件。而是必须等待所有的客户关闭SWF应用程序之后,才能删除和覆盖图像文件。但是等待用户关闭SWF是不现实的。其后果是灾难性的:新闻网站无法直接更新图片,线图不能实时更新。
解决此问题需要采取一定的实用技巧。可以尝试利用Loader对象打开另外一个文件,此时FlashPlayer会结束对原有外部文件的独占访问:
temploader.load(new URLRequest("imgdata/img2.gif"));
当执行此语句后,原有的“imgdata/img2.gif”就可以被外部程序修改了。这种技术的实际用法是在服务器上建立一个极小的替身图像文件(例如1像素×1像素)。在SWF程序中,始终在加载完图像后,利用上述技术建立图像的新副本,并删除原有图像。用Loader类的load()方法加载替身图像,解除对原有图像的锁定。