Spark SkinnableComponent 皮肤销毁策略
作为尝试解决应用程序内存泄漏问题的一部分,我们发现对于每个 SkinnableComponent
,skinDestructionPolicy
都设置为 “never”
默认情况下。
这意味着当使用静态皮肤部件时,皮肤将永远保留在内存中。
此外,主机组件中对partRemoved()的重写永远不会被触发。 因此,我们在 partAdded() 重写中添加的事件侦听器不会被删除,这实际上会导致视图和皮肤保留在内存中。
当进行大量视图切换时,这是不可接受的。
以下是我们现在如何解决此问题的示例:
public class ViewA extends SkinnableComponent
{
[SkinPart(required = "true")]
public var labelA:Label;
[SkinPart(required = "true")]
public var buttonA:Button;
public function ViewA()
{
super();
mx_internal::skinDestructionPolicy = 'auto';
}
override protected function getCurrentSkinState():String
{
return super.getCurrentSkinState();
}
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
trace("ViewA::partAdded " + partName);
if (instance == buttonA)
{
buttonA.addEventListener(MouseEvent.CLICK, buttonClickedHandler);
}
}
override protected function partRemoved(partName:String, instance:Object):void
{
trace("ViewA::partRemoved " + partName);
if (instance == buttonA)
{
buttonA.removeEventListener(MouseEvent.CLICK, buttonClickedHandler);
}
super.partRemoved(partName, instance);
}
override public function stylesInitialized():void
{
setStyle("skinClass", ViewASkin);
}
}
但是,使用 mx::internal
方法来规避此行为对我来说似乎相当奇怪。 有关这方面的文档也很少,因此任何想法都将受到欢迎。
干杯
As a part of trying to tackle a memory leak in our application, we discovered that for every SkinnableComponent
, the skinDestructionPolicy
is set to "never"
by default.
This means that when using static skin parts, the skin is forever detained in memory.
Furthermore, the override of a partRemoved() in the host component will never be triggered.
Hence, event listeners we add in the partAdded() override are not removed, which effectively causes views and skins to be kept in memory.
When doing a lot of view switches this is just not acceptable.
Here is an example of of how we are working around this now:
public class ViewA extends SkinnableComponent
{
[SkinPart(required = "true")]
public var labelA:Label;
[SkinPart(required = "true")]
public var buttonA:Button;
public function ViewA()
{
super();
mx_internal::skinDestructionPolicy = 'auto';
}
override protected function getCurrentSkinState():String
{
return super.getCurrentSkinState();
}
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
trace("ViewA::partAdded " + partName);
if (instance == buttonA)
{
buttonA.addEventListener(MouseEvent.CLICK, buttonClickedHandler);
}
}
override protected function partRemoved(partName:String, instance:Object):void
{
trace("ViewA::partRemoved " + partName);
if (instance == buttonA)
{
buttonA.removeEventListener(MouseEvent.CLICK, buttonClickedHandler);
}
super.partRemoved(partName, instance);
}
override public function stylesInitialized():void
{
setStyle("skinClass", ViewASkin);
}
}
However, using the mx::internal
way to circumvent this behavior seems rather odd to me.
Documentation about this is scarce as well, so any ideas will be very welcome.
Cheers
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据我的经验,在 Flex SDK 中使用
mx::internal
命名空间通常意味着以下内容:“您可以使用此功能,如果您知道自己要做什么的话正在做的事情,而且我们(Adobe,或未来的 Apache 社区)也不保证这个 API 在 Flex 的未来版本中永远不会改变”。因此,除非您非常关心向后兼容性,否则它的使用并没有真正的问题。如果您确实想避免使用它,您始终可以在子类中实现
skinDestructionPolicy="auto"
的行为。不需要编写太多代码:请注意,在
SkinnableComponent
类中,这两个事件侦听器在commitProperties()
方法中附加(或不附加,具体取决于策略)。我将其移至initialize()
方法,因为我们不再需要检查skinDestructionPolicy
属性中的更改。另请注意,如果同时将
mx::internal SkinDestructionPolicy
设置为“auto”
,则此解决方案可能会导致错误。In my experience the usage of the
mx::internal
namespace in the Flex SDK usually means something along the lines of: "you can use this functionality, if you know what you're doing, and also we (Adobe, or the Apache community in the future) don't guarantee that this API will never change in future versions of Flex".So there's no real issue with its usage, unless you're very concerned with backwards compatibility. If you really want to avoid using it, you can always just implement the behavior of
skinDestructionPolicy="auto"
in your subclass. There's not that much code to write:Note that in the
SkinnableComponent
class these two event listeners are attached (or not, depending on the policy) in thecommitProperties()
method. I moved that to theinitialize()
method because we don't need to check for changes in theskinDestructionPolicy
property anymore.Also note that this solution might cause an error if one did set
mx::internal skinDestructionPolicy
to"auto"
alongside.