如何从Adobe Flex的SWFLoader组件中卸载外部加载的SWF文件?
我有一个加载外部SWF文件并通过SWFLoader Flex组件在Adobe Flex / Air应用程序中播放它们的应用程序。我一直试图找到一种方法来将它们从按钮单击事件中卸载。我已经遍及Google了,似乎没有人能够做到这一点。我看到人们使用的代码组合为:
swfLoader.source = ""; // Removes the external link to the SWF. swfLoader.load(null); // Forces the loader to try to load nothing. // Note: At this point sound from the SWF is still playing, and // seems to still be playing in memory. flash.media.SoundMixer.stopAll(); // Stops the sound. This works on my development machine, but not // on the client's.
如果以这种方式关闭(隐藏)SWF,最终程序将崩溃。
有任何想法吗?我在各种论坛上都发现了很多帖子,人们遇到了同样的问题。我想我会在这里得到一个错误/不完整的答案,然后我的帖子将像往常一样陷入虚无,但无论哪种方式,请提前致谢!
编辑1:我无法编辑实际的SWF电影,它们是由客户端创建的。如果我无法关闭通过Flex打开的任何SWF,那么Flex体系结构不是问题吗?我唯一的选择是将SWF文件发送到Web浏览器吗?
解决方案
问题出在加载的SWF文件上,它根本不会清除音频。
尝试将卸载事件添加到如下的动画片段上:
MovieClip(event.target.content).loaderInfo.addEventListener(Event.UNLOAD, unloadMovieClipHandler); private function unloadMovieClipHandler(event:Event) : void { SoundMixer.stopAll(); }
请尝试以下方法:
try { new LocalConnection().connect('foo'); new LocalConnection().connect('foo'); } catch (e:*) {}
这将强制执行垃圾回收程序。如果SWF仍处于连接状态,则说明我们错过了某种连接,例如音频。
有几种强制GC的方法,由于它们会增加CPU的运行速度,因此很糟糕,但是好消息是Flash Player 10中出现了一种正式的方法:
unloadAndStop
链接:http://www.gskinner.com/blog/archives/2008/07/unloadandstop_i.html
在此之前,恐怕我们将不得不像上面显示的那样通过黑客强制使用它。
我们尚未显示所有代码,因此我将假定我们未使用Loader类的unload方法。 swfLoader.load(null)对我来说似乎也不对,因为load方法需要一个URLRequest对象。如果要在最后清理所有内容,请将对象的值设置为null,而不是调用null加载。我们仍在收听音频的事实表明数据尚未卸载,或者音频文件未驻留在已卸载的内容中。让我们来看一下。
下面的例子
var loader:Loader = new Loader(); var request:URLRequest = new URLRequest('test.swf'); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSwfLoad, false, 0, true); function onSwfLoad(e:Event):void { addChild(loader); loader.contentLoaderInfo.addEventListener(Event.UNLOAD, onLoaderUnload, false, 0, true); loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onSwfLoad, false); } function onLoaderUnload(e:Event):void { trace('LOADER WAS SUCCESSFULLY UNLOADED.'); } //Now to remove this with the click of a button, assuming the buttons name is button_mc button_mc.addEventListener(MouseEvent.MOUSE_DOWN, onButtonDown, false, 0, true); function onButtonDown(e:MouseEvent):void { loader.unload(); loader.contentLoaderInfo.removeEventListener(Event.UNLOAD, onLoaderUnload); //When you want to remove things completely from memory you simply set their value to null. loader = null; button_mc.removeEventListener(MouseEvent.MOUSE_DOWN, onButtonDown); }
我确实希望这会有所帮助,很抱歉,如果有多余的地方,但是在没有看到代码的情况下,我无法确切知道处理方式。
问题是,创建不良的SWF可能会沉没应用程序,而与此相关的许多问题将在Flash Player 10中得到解决,就像其他人提到的那样。但是,无论使用哪种平台,如果我们加载第三方代码,都将始终有遇到问题的风险,它总是有可能包含错误,内存泄漏或者恶意代码。除非我们可以将内容加载到沙箱中(并且至少不能在Flash中加载),否则加载不良内容会使应用程序崩溃,就这么简单。
很遗憾地说,除非我们可以保证所加载内容的质量,否则就不能保证自己的应用程序的质量。 Flash开发人员以编写泄漏或者无法卸载的内容而臭名昭著,因为Flash可以很容易地做错事情,尤其是对于时间线上的事情。直接加载任何我们无法控制的Flash内容非常危险。
... isn't that a problem with the Flex architecture?
是的,它通常还会影响Flash。除非可以利用FP10(AIR 1.5)中的Loader.unloadAndStop()方法,否则即使我们使用`Loader.unload(),也不能保证外部加载的内容不会继续消耗内存和CPU资源。方法。 (说实话,我不是100%肯定会保证释放资源,但我可能是悲观主义者。)
其次,我们最好坚持所加载内容的创建者遵循一系列准则,包括公开诸如dispose()
之类的方法,应用可以调用该方法以要求其释放尽可能多的资源。在unload()
之前。如果这不可能,那么每次加载外部swf时,应用程序几乎肯定会在内存和cpu使用上膨胀。对不起。
如果能让我们感觉更好,那么我们并不孤单。 ;)
我通常会远离SWFLoader并使用mx.modules包中的类。
Flex具有启用此类行为的模块系统。我们可以在这里查看:http://livedocs.adobe.com/flex/3/html/help.html?content=modular_3.html。通常,动态加载和卸载swf组件非常棘手,特别是如果那些模块修改了应用程序中的任何全局状态(样式等)。但是,如果为模块创建接口,然后加载/卸载的每个类都实现该接口并扩展flex模块类,则可以干净地加载和卸载它们。