4
votes

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;
        }
    }
2
Make sure each module's children components also have their eventListeners removed. I don't suppose any of these modules have AdvancedDataGrids with HierarchicalData do they? - Jason Towne
Yes, they all have Advanced Datagrids. Some modules have popups which leak too, but I don't need to open them for the app to leak data when navigating different modules. - enon
Do those AdvancedDataGrids use HierarchicalData? I ran into a similar issue where my AdvancedDataGrids were causing memory leaks. - Jason Towne
I don't know what you mean by HierarchicalData, sorry :S. The DataGrids are written in every Module as traditional mxml, and are assigned dataProviders as arrayCollections from result handlers. - enon

2 Answers

1
votes

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 = {};
}
2
votes

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