2011-02-12 46 views
0

我有一个简单的,可重现的内存泄漏与Spark Combo盒相关,但是我确信它必须是我做错的事情,而不是SDK错误。Spark Combox内存泄漏

// Application.mxml 
<?xml version="1.0" encoding="utf-8"?> 
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
       xmlns:s="library://ns.adobe.com/flex/spark" 
       xmlns:mx="library://ns.adobe.com/flex/mx"> 
    <s:layout> 
     <s:VerticalLayout /> 
    </s:layout> 
    <fx:Script> 
     <![CDATA[ 
      import mx.events.FlexEvent; 

      private var hasElement:Boolean; 
      protected function toggleContainer():void 
      { 
       if (hasElement) 
       { 
        button.setFocus(); 
        comboBoxContainer.removeAllElements(); 
        hasElement = false; 
       } else { 
        var vew:ComboBoxView = new ComboBoxView(); 
        comboBoxContainer.addElement(vew); 
        hasElement = true; 
       } 
      } 
     ]]> 
    </fx:Script> 
    <s:Button id="button" label="Add container" click="toggleContainer()" /> 
    <s:Group id="comboBoxContainer" /> 
</s:Application> 


// ComboBoxView.mxml 

<?xml version="1.0" encoding="utf-8"?> 
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009" 
     xmlns:s="library://ns.adobe.com/flex/spark" 
     xmlns:mx="library://ns.adobe.com/flex/mx" 
     > 
    <s:ComboBox /> 
</s:VGroup> 

当对的Flex 4.1编译,这似乎创造了内存泄漏,其中ComboBoxView从未GC'd - 因为挥之不去的参考组合框。

下面是来自分析器的输出: enter image description here

重现步骤:

  • Application.mxml创建项目并ComboBoxView.mxml
  • 使用Flex 4.1
  • 启动Application.mxml编译项目与分析器
  • 创建一个内存快照
  • 点击按钮,将视图添加到舞台
  • 再次单击该按钮可从舞台
  • 运行垃圾收集器
  • 创建另一个内存快照
  • 查看挥之不去两者对象remvoe视图内存快照

注 - 当应用程序针对Flex Hero进行编译时,不会发生这种情况。

看起来好像这是一个错误,但我不能相信ComboBox有内存泄漏 - 当然这会在4.1发货之前被修复?

我在这里做错了什么?为什么视图不是GC?

更新我已经做了进一步的调查,并认为问题在于ComboBoxSkin使用RichEditableText组件的问题。在这里看到详细信息: Spark memory leaks

回答

0

MXML很棘手有时候是因为你永远不知道幕后到底发生了什么(除非你使用-keep属性并查看)。

但是,它看起来像我从来没有空组合框引用。删除容器的子项与从内存中删除该实例不同。例如,在Flextras Calendar组件中,随着月份的变化,我们很少去除显示日期。根据月份的不同,可能会显示28到31天之间的任何地方。但是,如果你在一个31天的时间内,并且在30天内切换到一个月,那么我们不会清空那些额外的日期渲染器,我们只是将它们缓存在“unusedDays”数组中,然后让它们准备下一个月份切换时间。

ListBase类做类似的事情,我相信Flex 4甚至有一个名为useVirtualLayout的属性来控制这些东西是如何保存在内存中的。

我希望这不是一个漫长的,或自我放纵的解释,我希望它是有道理的。

我认为你需要做些什么来清空ComboBox。我想尝试的第一件事就是给组合框的ID:

<?xml version="1.0" encoding="utf-8"?> 
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009" 
     xmlns:s="library://ns.adobe.com/flex/spark" 
     xmlns:mx="library://ns.adobe.com/flex/mx" 
     > 
    <s:ComboBox id="myComboBox" /> 
</s:VGroup> 

然后在你的ActionScript代码,创建ComboBoxView的一个实例(不能运行本地):

protected var vew:ComboBoxView = new ComboBoxView(); 

再处理垃圾收集这样的:

 if (hasElement) 
     { 
      button.setFocus(); 
      comboBoxContainer.removeAllElements(); 
      comboBoxContainer.myComboBox = null; 
      comboBoxContainer = null; 
      hasElement = false; 
     } else { 
      var vew:ComboBoxView = new ComboBoxView(); 
      comboBoxContainer.addElement(vew); 
      hasElement = true; 
     } 
    } 

我没做测试自己,我的直觉是需要不是所有这些步骤;但我怀疑我的做法可能是正确的。

+0

类似的问题我测试了类似的方法。清空组合框允许父项GC'd,但组合框仍然存在。请注意,GC Root的路径不是通过父节点,而是通过ComboBox的子节点(在本例中为TLF underling)。因此,将其从父项中移除并不符合垃圾回收的条件。 – 2011-02-12 04:36:42