【问题标题】:How do I unload a externally loaded SWF file from a SWFLoader component in Adobe Flex?如何从 Adob​​e Flex 中的 SWFLoader 组件卸载外部加载的 SWF 文件?
【发布时间】:2008-09-22 21:57:27
【问题描述】:

我有一个应用程序可以加载外部 SWF 文件并通过 SWFLoader Flex component 在 Adob​​e Flex / Air 应用程序中播放它们。我一直在尝试找到一种从按钮单击事件中卸载它们的方法。我在 Google 上搜索的范围很广,似乎没有人能够在没有 hack 的情况下做到这一点。我看到人们使用的代码组合是:

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 浏览器是我唯一的选择吗?

【问题讨论】:

  • 编辑:似乎是 Flash 9 的一个错误。希望现在已修复:D

标签: apache-flex air adobe swfloader


【解决方案1】:

...这不是 Flex 架构的问题吗?

是的,而且它通常也会影响 Flash。在您可以利用 FP10 (AIR 1.5) 中的 Loader.unloadAndStop() 方法之前,您无法保证外部加载的内容不会继续消耗内存和 cpu 资源,即使您使用 Loader.unload() 方法也是如此。 (老实说,我不能 100% 确定即使这样也能保证释放资源,但也许我是个悲观主义者。)

下一个最好的事情是让您坚持让您加载的内容的创建者遵守一组准则,包括公开类似 dispose() 方法的内容,您的应用可以调用该方法来要求它释放尽可能多的资源可能在你之前unload() 它。如果这是不可能的,那么每次您加载外部 swf 时,您的应用程序几乎肯定会在内存和 cpu 使用方面膨胀。对不起。

如果它让您感觉更好,那么您并不孤单。 ;)

【讨论】:

  • 其实是在Loader.unloadAndStop() 失败后才发现这个帖子的。看不到希望!
  • 奇数。你能详细说明吗?如果不存在,甚至可以问一个问题!
【解决方案2】:

创建不当的 SWF 可能会导致应用程序崩溃,这是一个问题,正如其他人所提到的,许多与此相关的问题将在 Flash Player 10 中得到解决。但是,无论在哪个平台上,如果您加载第三方代码,您总是会遇到问题,它总是有可能包含错误、内存泄漏或彻头彻尾的恶意代码。除非您可以将内容加载到沙箱中(并且您不能在 Flash 中,至少目前还不能),否则加载不好的东西会使您的应用程序崩溃,就这么简单。

很抱歉,除非您能保证加载内容的质量,否则您无法保证自己的应用程序的质量。 Flash 开发人员因编写泄漏或无法卸载的东西而臭名昭著,因为 Flash 很容易做错事,特别是对于时间线上的东西。加载任何您无法直接控制的 Flash 内容是非常危险的。

【讨论】:

    【解决方案3】:

    最好的解决办法是

    swfLoader.autoLoad = false;
    swfLoader.unloadAndStop();
    swfLoader.autoLoad = true;
    

    通过这种方式,您可以停止播放器,从内存中卸载内容并避免声音继续播放。 干杯

    【讨论】:

      【解决方案4】:

      问题在于加载的 swf,它本身并没有清理音频。 尝试像这样将卸载事件附加到影片剪辑上:

      MovieClip(event.target.content).loaderInfo.addEventListener(Event.UNLOAD, unloadMovieClipHandler);
      private function unloadMovieClipHandler(event:Event) : void
      {
        SoundMixer.stopAll();                           
      } 
      

      【讨论】:

        【解决方案5】:

        我通常会远离 SWFLoader 并使用 mx.modules 包中的类。

        Flex 有一个模块系统可以实现这种行为。你可以在这里查看:http://livedocs.adobe.com/flex/3/html/help.html?content=modular_3.html。通常,动态加载和卸载 swf 组件很棘手,尤其是当这些模块修改应用程序中的任何全局状态(样式等)时。但是,如果您为模块创建一个接口,然后您加载/卸载的每个类都实现该接口并扩展 flex 模块类,那么您可以干净地加载和卸载它们。

        【讨论】:

          【解决方案6】:

          尝试以下方法:

          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

          在那之前,恐怕你必须像我上面展示的那样用黑客来强制它。

          【讨论】:

          • GC hack 对我来说似乎不是最佳实践。我只建议在开发环境中使用它来帮助获得更有意义的内存使用值。在生产中依赖它可能会让您以后后悔。
          【解决方案7】:

          您还没有显示所有代码,所以我假设您没有使用 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); }

          我确实希望这会有所帮助,如果它是多余的,我很抱歉,但是如果没有看到您的代码,我无法确切知道您是如何处理这个问题的。

          【讨论】:

          • 我没有使用 Loader,我使用的是 Flex SWFLoader 组件。不过,明天早上我会试试 Loader 类。谢谢...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-09-22
          • 1970-01-01
          • 1970-01-01
          • 2010-09-19
          • 1970-01-01
          • 1970-01-01
          • 2012-02-23
          相关资源
          最近更新 更多