Spark Combox内存泄漏

时间:2011-02-12 01:34:31

标签: flex memory-leaks flex4 flex-spark

我有一个与Spark Combo框相关的简单,可重现的内存泄漏,但是我确信它一定是我做错了,而不是SDK错误。

// 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-因为对ComboBox的延迟引用。

以下是探查器的输出: enter image description here

重现的步骤:

  • 使用Application.mxmlComboBoxView.mxml
  • 创建项目
  • 使用Flex 4.1编译项目
  • 使用分析器启动Application.mxml
  • 创建内存快照
  • 单击按钮将视图添加到舞台
  • 再次单击该按钮以从舞台上移除视图
  • 运行垃圾收集器
  • 创建另一个内存快照
  • 查看两个内存快照之间的延迟对象

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

好像这是一个bug,但我无法相信ComboBox有内存泄漏 - 这肯定会在4.1发布之前修复过吗?

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

更新我已对此进行了进一步调查,并认为问题在于ComboBoxSkin使用的RichEditableText组件存在问题。详情请见: Spark memory leaks

2 个答案:

答案 0 :(得分:1)

http://www.iampj.com/search/label/combobox%20memory%20leak

我在flex 3中遇到过类似的问题

答案 1 :(得分:0)

MXML有时很棘手,因为你永远不知道幕后发生了什么(除非你使用-keep属性和外观)。

但是,在我看来,你永远不会将ComboBox引用归零。删除容器的子容与从内存中删除该实例不同。例如,在Flextras日历组件中,随着月份的变化,我们从显示中删除天数并不罕见。根据月份的不同,可能会显示28到31天之间的任何时间。但是,如果你在31个月的一个月内切换到30天的一个月,那么我们不会将那些额外的日期渲染器归零,我们只是将它们缓存在“unusedDays”数组中然后我们让它们为下一个做好准备月份的时间切换。

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

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

我认为您需要做一些事情来使ComboBox无效。我要尝试的第一件事是给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;
        }
    }

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