【问题标题】:Adobe Flex: memory leak when pushView an popViewAdobe Flex:pushView 和 popView 时内存泄漏
【发布时间】:2013-11-18 11:46:23
【问题描述】:

我使用 Flex Builder 在 Adob​​e Flex 中构建的应用程序遇到内存泄漏问题。使用 30-40 分钟后,它开始变得越来越慢。

应用程序将图像显示为目录,但当我推送和弹出视图时,我的记忆力会大大增加。

我的想法是,如果我将所有对象设置为 null 并处置我使用的所有位图数据,我可以释放足够的内存来继续使用应用程序而没有问题,但似乎问题不存在。

我的应用 menuView.mxml、categoriesView.mxml 和 productsView.mxml 中有 3 个视图。

我的应用程序在我的电脑(不是平板电脑)中启动,总内存:47Mb 和私有内存:88 MB

在推送和弹出视图 5 次后,我得到 TotalMemory: 61Mb 和 Private Memory : 101 MB

想象一下,如果我这样做几次。该应用程序在我的 Ipad 或三星 Galaxy Tab 中开始运行缓慢。

为什么会这样?我不知道如何解决这个问题。

请帮忙!非常感谢!!

我在下面放了一些代码。

当我在 menuView 中时,我使用以下代码将视图从 menuView 推送到 categoriesView

protected function button3_clickHandler(event:MouseEvent):void
{
    if((FlexGlobals.topLevelApplication.getIdClienteServidorCompraActual( )!=null)&&  (FlexGlobals.topLevelApplication.getIdClienteServidorCompraA ctual()>0))
            {
                navigator.pushView(categoriesView);
            }
}

当我在 categoriesView 中时,我使用以下代码将视图从 categoriesView 推送到 productsView。在这个视图中,每个类别都有 3 个按钮。

protected function buttonC1_clickHandler(event:MouseEvent):void
{
            //Categoria general con todos
            var ab:ArrayCollection =  getIdAmbienteServidor();
           cleanMemory();
            navigator.pushView(productsView, null);
}



private function cleanMemory():void
{
    result.splice(0);
    result = null;
    System.gc();
}

当我在 productsView 中时,我使用以下代码将视图从 productsView 弹出(我使用 PUSH INSTEAD OF POP,因为我有不同的选项)到 categoriesView 。

protected function button1_clickHandler(event:MouseEvent):void
{
    cleanMemory();               
    navigator.pushView(menuView);        
}

private function cleanMemory():void
{
    if(image1 != null)
    {
        image1.source = "";
        if(image1.bitmapData != null)
        {
            image1.bitmapData.dispose();
        }
    }
    if(image2 != null)
    {
        image2.source = "";

        if(image2.bitmapData != null)
        {
            image2.bitmapData.dispose();
        }
    }

    if(result != null)
    {
        result.splice(0);
        result = null;
    }
    if(result1 != null)
    {
        result1.splice(0);
        result1 = null;
    }
    if(result2 != null)
    {
        result2.splice(0);
        result2 = null;
    }

    dbConnection = null;
    object1 = null;
    object2 = null;
    dataToSave = null;
    cGreyImageSmallAsset = null;
    cRedImageSmallAsset.bitmapData.dispose();
    cRedImageSmallAsset = null;
    cOrangeImageAsset.bitmapData.dispose();
    cOrangeImageAsset = null;
    cGreenImageAsset.bitmapData.dispose();
    cGreenImageAsset = null;
    cPinkImageAsset.bitmapData.dispose();
    cPinkImageAsset = null;
    cBlueImageAsset.bitmapData.dispose();
    cBlueImageAsset = null;
    cGreyImageAsset.bitmapData.dispose();
    cGreyImageAsset = null;
    cRedImageAsset.bitmapData.dispose();
    cRedImageAsset = null;
    cGreenImageSmall = null;
    cOrangeImageSmall = null;
    cPinkImageSmall = null;
    cBlueImageSmall = null;
    cGreyImageSmall = null;
    cRedImageSmall= null;
    cGreenImage = null;
    cPinkImage = null;
    cBlueImage= null;
    cGreyImage = null;
    cRedImage= null;
    cOrangeImage= null;
    System.gc();
}

我加载图像。

private function setImages():void
{               
    if(object1!=null)
    {                   
        panelLeft.visible = true;
        buttonLeftMore.visible = true;
        image1.source = "file://" + File.applicationStorageDirectory.nativePath + "/b"+object1.idArchivo+"_500.jpg";
        setObject1MainTexts();
     }
     else
     {
         image1.source = "";
         panelLeft.visible = false;
         buttonLeftMore.visible = false;
     }

     if(object2!=null)
     {   
         panelRight.visible = true;
         buttonRightMore.visible = true;
         image2.source = "file://" + File.applicationStorageDirectory.nativePath + "/b"+object2.idArchivo+"_500.jpg";
         setObject2MainTexts();
     }
     else
     {
         image2.source = "";
         panelRight.visible = false;
         buttonRightMore.visible = false;
     }
  }

当我在 categoriesView 中时,我使用以下代码将视图从 categoriesView 弹出(我使用 PUSH INSTEAD OF POP,因为我有不同的选项)到 menuView。

protected function button1_clickHandler(event:MouseEvent):void
{
    cleanMemory();
    navigator.pushView(menuPrincipalBelda);
}

private function cleanMemory():void
{
    result.splice(0);
    result = null;
    System.gc();
}

提前致谢!

【问题讨论】:

  • 您永远不必手动运行 GC,也很少必须在 DisplayObject 上运行“清理”例程。只需将其从显示列表中删除并取消对它的任何引用就足够了。这听起来更像是您在某处泄漏了对您的视图的引用,从而阻止了它在 GC 中被清理。您是否检查了分析器中的泄漏?
  • 我们在使用 Flash Builder 开发移动应用程序时也遇到了这个问题。感谢这个帖子,我会试试这个建议。

标签: apache-flex memory memory-leaks air adobe


【解决方案1】:

我发现了问题:我没有删除 EventListener,现在工作正常。

我给你们举几个例子。如果你不删除它们,那么内存会增加很多!小心这个。

stage.addEventListener("keyUp", handleButtons, false, 1);
stage.removeEventListener("keyUp",handleButtons,false);
xeasy.addEventListener(ResultEvent.RESULT, AppWS_resultHandler);
xeasy.removeEventListener(ResultEvent.RESULT,AppWS_resultHandler, false);

谢谢大家!!

【讨论】:

    【解决方案2】:

    请记住,Flex Builder 使用 Flash 虚拟机,这会在认为有必要时释放内存,即使您尝试强制他清理垃圾收集器,如果您有可用内存并且认为没有必要,垃圾收集器也不会这样做。 在应用程序中您需要的图像中测试嵌入电影,而不是不断加载。因为这可能会让一些低级的关系。

    问候

    【讨论】:

    • 感谢您的回复,matilu。你指的是嵌入的图像吗?,我使用 var 喜欢我写下的这些来获取我在视图中使用的图像。嵌入(source=".​​./img/cgreen_small.png")] 私有变量 cGreenImageSmall:Class; [嵌入(source=".​​./img/corange_small.png")] 私有变量 cOrangeImageSmall:Class;私有变量 cGreenImageSmallAsset:BitmapAsset;私有变量 cOrangeImageSmallAsset:BitmapAsset;
    • 我的意思是,也许你最好使用嵌入图像(取决于你需要加载多少图片,但在所有这些中,不要超过 300kb,去吧),因为文件的持续加载可能会使关系内存不足。还要检查您上传的图像上是否有带有样式的背景、事件侦听器。也不是很好的启动弹出窗口。无法看到详细的应用程序我无法让我知道还有什么可以。我希望你能解决问题。问候
    • Matilu,感谢您的 cmets。我会尝试一下,让你知道它有帮助。
    【解决方案3】:

    当我与 GC 合作时,我发现尝试几种不同的方法变得很有优势!随着时间的推移,我总共使用了 3 个,但目前只能找到一个,因为这是这个应用程序中明显更好的一个。所以就在这里,如果需要,我可以发送其他两个,也必须寻找它们!

            private var gcCount:int;
    
            private function startGCCycle():void {
    
                gcCount = 0;
                addEventListener(Event.ENTER_FRAME, doGC);
            }
            private function doGC(evt:Event):void {
    
                flash.system.System.gc();
    
                if(++gcCount > 1) {
    
                    removeEventListener(Event.ENTER_FRAME, doGC);
                    setTimeout(lastGC, 40);
                }
            }
            private function lastGC():void{
                flash.system.System.gc();
            }
        ]]>
    

    我只是在看其他东西,你也应该尝试一下,它对我很有效!

    FlexGlobals.topLevelApplication.deleteReferenceOnParentDocument(this) 我在 MXML 中的 creationComplete 中使用了这些,我必须一个接一个地打开 45 个主画布,但每次都有三个 PopUps = 180,这在我处理 GC 的方式中很容易处理在!关于aktell

    【讨论】:

    • 谢谢 aktell,如果我对 GC 有任何问题,我会听取您的意见。
    • 没关系!但是我看到您没有使用 IF 可能并且在您的第二个 EventListener 上使用相同的代码??? xeasy.addEventListener(ResultEvent.RESULT, AppWS_resultHandler);去测试 ! xeasy.addEventListener(ResultEvent.RESULT, AppWS_resultHandler, false, 1);以及在一个函数中使用 ADD 并在另一个函数中使用 REMOVE。问候阿克特尔
    猜你喜欢
    • 1970-01-01
    • 2010-12-02
    • 2013-11-08
    • 2016-05-03
    • 2011-11-25
    • 2010-11-19
    • 2014-09-27
    • 2013-07-31
    • 1970-01-01
    相关资源
    最近更新 更多