Flex ModuleLoader 组件导致内存泄漏。如何正确卸载模块?

发布于 2024-11-26 16:55:40 字数 2430 浏览 1 评论 0原文

该应用程序太大,无法在此描述,但我可以告诉您,我有多达 20 个或更多模块可供客户端随时使用。如果我继续加载一个又一个屏幕,我的应用程序可能会占用 500MB 甚至更多。

我用来加载和卸载模块的脚本是:

public function createModule(modulo:String):void {
                if(moduleLoader != null){
                    moduleLoader.unloadModule();
                    //moduleLoader.url = null;
                    moduleLoader.url = "com/oss/facturable/components/" + modulo + "?version=" + model.configXML.versionApp;    
                    moduleLoader.loadModule();
                }       
            }
            private function errorHandler(e:ModuleEvent):void {
                Alert.show("No se ha podido cargar el modulo. Contacte al departamento técnico.");
            }

加载模块的容器:

<s:BorderContainer width="98%" height="98%" includeIn="mainState" styleName="bcModuleLoader" top="100">
                    <s:layout>
                        <s:HorizontalLayout paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10"/>
                    </s:layout>
                    <s:Scroller width="100%" height="100%">
                        <s:Group>
                            <mx:ModuleLoader id="moduleLoader" error="errorHandler(event)" width="100%" height="100%" horizontalAlign="center" verticalAlign="top" creationComplete="createModule('bandejaEntrada.swf')"/>              
                        </s:Group>
                    </s:Scroller>
 </s:BorderContainer>

每当我单击我认为与此处发布无关的菜单选项时,都会调用 createModule 函数。总而言之,这就是我现在让它工作和泄漏的一切:S

这是官方的 unloadModule 函数,我认为,从它的外观来看,内存应该很好地分配给这个东西,我的意思是,看!它删除所有事件监听器和子对象。为什么我的内存在卸载时保持不变,而当我打开新模块时加载更多内存?!啊啊!

public function unloadModule():void
    {
        if (child)
        {
            removeChild(child);
            child = null;
        }

        if (module)
        {
            module.removeEventListener(ModuleEvent.PROGRESS,
                                       moduleProgressHandler);
            module.removeEventListener(ModuleEvent.SETUP, moduleSetupHandler);
            module.removeEventListener(ModuleEvent.READY, moduleReadyHandler);
            module.removeEventListener(ModuleEvent.ERROR, moduleErrorHandler);

            module.unload();
            module.removeEventListener(ModuleEvent.UNLOAD, moduleUnloadHandler);
            module = null;
        }
    }

The application is too big to describe here, but I can tell you I have up to 20 modules or more that the client can use at any time. And if I go on loading screen after screen, my application can ocuppy 500MB and more.

The script that I use to load and unload modules is:

public function createModule(modulo:String):void {
                if(moduleLoader != null){
                    moduleLoader.unloadModule();
                    //moduleLoader.url = null;
                    moduleLoader.url = "com/oss/facturable/components/" + modulo + "?version=" + model.configXML.versionApp;    
                    moduleLoader.loadModule();
                }       
            }
            private function errorHandler(e:ModuleEvent):void {
                Alert.show("No se ha podido cargar el modulo. Contacte al departamento técnico.");
            }

The Container in which the module is loaded:

<s:BorderContainer width="98%" height="98%" includeIn="mainState" styleName="bcModuleLoader" top="100">
                    <s:layout>
                        <s:HorizontalLayout paddingLeft="10" paddingRight="10" paddingTop="10" paddingBottom="10"/>
                    </s:layout>
                    <s:Scroller width="100%" height="100%">
                        <s:Group>
                            <mx:ModuleLoader id="moduleLoader" error="errorHandler(event)" width="100%" height="100%" horizontalAlign="center" verticalAlign="top" creationComplete="createModule('bandejaEntrada.swf')"/>              
                        </s:Group>
                    </s:Scroller>
 </s:BorderContainer>

The createModule function is called whenever I click on a menu option that I think is irrelevant to post here. All in all, this is everything I have for now to make it work and leak :S

This is the official unloadModule function, I thought, by the looks of it, that the memory should be well allocated with this thing, I mean, look! It removes all the eventListeners and child objects. How come my memory stays the same when unloading, and loads more memory on top of it when I open a new module?! Augh!

public function unloadModule():void
    {
        if (child)
        {
            removeChild(child);
            child = null;
        }

        if (module)
        {
            module.removeEventListener(ModuleEvent.PROGRESS,
                                       moduleProgressHandler);
            module.removeEventListener(ModuleEvent.SETUP, moduleSetupHandler);
            module.removeEventListener(ModuleEvent.READY, moduleReadyHandler);
            module.removeEventListener(ModuleEvent.ERROR, moduleErrorHandler);

            module.unload();
            module.removeEventListener(ModuleEvent.UNLOAD, moduleUnloadHandler);
            module = null;
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嗳卜坏 2024-12-03 16:55:40

如果您使用的是 Flex 4.5,请尝试改用
更多详细信息:此处

If you are using Flex 4.5, try to use <s:ModuleLoader/> instead.
More details : here

贱人配狗天长地久 2024-12-03 16:55:40

来自这篇文章

使用HierachicalData时通过 AdvancedDataGrid,该控件通过使用 IHierarchicalCollectionView 界面来跟踪分层和分组数据。该接口有一个 openNodes 属性,其中包含一个对象数组,这些对象表示当前在 AdvancedDataGrid 中打开的数据提供程序的节点。

如果您用新的数据提供程序替换数据提供程序,AdvancedDataGrid 控件不会清除 openNodes 属性。由于 openNodes 属性包含对旧数据提供程序中对象的引用,因此无法通过垃圾回收从内存中删除这些对象。为了确保可以从内存中删除旧的数据提供程序,请在替换数据提供程序时使用事件处理程序清除 openNodes 属性。

将事件侦听器添加到数据提供程序的 CollectionEvent.COLLECTION_CHANGE 事件以清除 openNodes 属性。

// Handle the colectionChange event.
private function removeOpenNodes(event:CollectionEvent):void 
{
  if(event.kind == CollectionEventKind.RESET)
    IHierarchicalCollectionView(adg.dataProvider).openNodes = {};
}

From this article:

When using HierachicalData with an AdvancedDataGrid, the control keeps track of hierarchical and grouped data by using the IHierarchicalCollectionView interface. The interface has an openNodes property contains an Array of objects that represent the nodes of the data provider that are currently open in the AdvancedDataGrid.

If you replace the data provider with a new data provider, the AdvancedDataGrid control does not clear the openNodes property. Because the openNodes property contains references to objects in the old data provider, the objects cannot be removed from memory by garbage collection. To ensure that the old data provider can be removed from memory, use an event handler to clear the openNodes property when you replace the data provider.

Add an event listener to the data provider’s CollectionEvent.COLLECTION_CHANGE event to clear the openNodes property.

// Handle the colectionChange event.
private function removeOpenNodes(event:CollectionEvent):void 
{
  if(event.kind == CollectionEventKind.RESET)
    IHierarchicalCollectionView(adg.dataProvider).openNodes = {};
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文