我有一个与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的延迟引用。
以下是探查器的输出:
重现的步骤:
Application.mxml
和ComboBoxView.mxml
注意 - 当针对Flex Hero编译应用程序时,不会发生这种情况。
好像这是一个bug,但我无法相信ComboBox有内存泄漏 - 这肯定会在4.1发布之前修复过吗?
我在这里做错了什么?为什么视图不是GC?
更新我已对此进行了进一步调查,并认为问题在于ComboBoxSkin使用的RichEditableText组件存在问题。详情请见: Spark memory leaks
答案 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;
}
}
我没有自己测试,我的直觉是并非所有这些步骤都需要;但我怀疑我的方法可能是正确的。