Spark SkinnableComponent皮肤销毁策略

3
作为解决我们应用程序中的内存泄漏问题的一部分,我们发现默认情况下每个SkinnableComponentskinDestructionPolicy都设置为"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 方法来规避这种行为对我来说似乎相当奇怪。关于此的文档也很少,因此任何想法都将非常受欢迎。
干杯

2
遇到了完全相同的问题。扫描了Flex代码库,查找是否可以通过设置另一个(公共)属性来设置此属性,并发现整个SDK中只有一个出现:ViewMenuItem(移动设备)在内部将其skinDestructionPolicy设置为“auto”。因此似乎没有其他方法,只能使用mx::internal命名空间来设置该属性。 - RIAstar
1个回答

3
根据我的经验,在Flex SDK中使用mx::internal命名空间通常意味着:“如果你知道自己在做什么,你可以使用此功能,但我们(Adobe或未来的Apache社区)不保证此API在Flex的未来版本中永远不会更改”。
因此,除非您非常关注向后兼容性,否则其使用没有实际问题。如果您真的想避免使用它,您可以在您的子类中实现skinDestructionPolicy =“auto”的行为。需要编写的代码并不多:
    override public function initialize():void {
        addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
        addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);

        super.initialize();
    }

    private function addedToStageHandler(event:Event):void {
        if (skin == null) attachSkin();
    }

    private function removedFromStageHandler(event:Event):void {
        detachSkin();
    }

请注意,在SkinnableComponent类中,这两个事件侦听器是在commitProperties()方法中附加的(或者不附加,取决于策略)。我将其移动到initialize()方法中,因为我们不再需要检查skinDestructionPolicy属性是否发生变化。
另请注意,如果同时将mx::internal skinDestructionPolicy设置为"auto",这种解决方案可能会导致错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接