Spark SkinnableComponent skinDestructionPolicy [英] Spark SkinnableComponent skinDestructionPolicy

查看:27
本文介绍了Spark SkinnableComponent skinDestructionPolicy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为尝试解决应用程序内存泄漏的一部分,我们发现对于每个 SkinnableComponentskinDestructionPolicy 都设置为 never" 默认.

这意味着当使用静态皮肤部件时,皮肤会永远留在内存中.
此外,永远不会触发宿主组件中 partRemoved() 的覆盖.因此,我们在 partAdded() 覆盖中添加的事件侦听器不会被删除,这有效地导致视图和皮肤保留在内存中.

当进行大量视图切换时,这是不可接受的.

以下是我们如何解决此问题的示例:

公共类 ViewA 扩展 SkinnableComponent{[SkinPart(required = "true")]public var labelA:标签;[SkinPart(required = "true")]public var buttonA:按钮;公共函数 ViewA(){极好的();mx_internal::skinDestructionPolicy = 'auto';}覆盖受保护的函数 getCurrentSkinState():String{返回 super.getCurrentSkinState();}覆盖受保护的函数 partAdded(partName:String, instance:Object):void{super.partAdded(partName, instance);trace("ViewA::partAdded" + partName);如果(实例 == buttonA){buttonA.addEventListener(MouseEvent.CLICK, buttonClickedHandler);}}覆盖受保护的函数 partRemoved(partName:String, instance:Object):void{trace("ViewA::partRemoved" + partName);如果(实例 == buttonA){buttonA.removeEventListener(MouseEvent.CLICK, buttonClickedHandler);}super.partRemoved(partName, instance);}覆盖公共函数stylesInitialized():void{setStyle("skinClass", ViewASkin);}}

然而,使用 mx::internal 方法来规避这种行为对我来说似乎很奇怪.这方面的文档也很少,因此欢迎提出任何想法.

干杯

解决方案

根据我的经验,在 Flex SDK 中使用 mx::internal 命名空间通常意味着:可以使用此功能,如果您知道自己在做什么,并且我们(Adobe 或未来的 Apache 社区)不保证此 API 在未来的 Flex 版本中永远不会改变".

所以它的使用没有真正的问题,除非你非常关心向后兼容性.如果你真的想避免使用它,你总是可以在你的子类中实现 skinDestructionPolicy="auto" 的行为.没有那么多代码要写:

 覆盖公共函数 initialize():void {addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);addEventListener(Event.REMOVED_FROM_STAGE,removedFromStageHandler);超级初始化();}私有函数 addedToStageHandler(event:Event):void {if (skin == null) attachSkin();}私有函数removedFromStageHandler(event:Event):void {分离皮肤();}

请注意,在 SkinnableComponent 类中,这两个事件侦听器在 commitProperties() 方法中附加(或不附加,取决于策略).我将其移至 initialize() 方法,因为我们不再需要检查 skinDestructionPolicy 属性中的更改.

另请注意,如果 didmx::internal skinDestructionPolicy 设置为 "auto",则此解决方案可能会导致错误.>

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

解决方案

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:

    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();
    }

Note that in the SkinnableComponent class these two event listeners are attached (or not, depending on the policy) in the commitProperties() method. I moved that to the initialize() method because we don't need to check for changes in the skinDestructionPolicy property anymore.

Also note that this solution might cause an error if one did set mx::internal skinDestructionPolicy to "auto" alongside.

这篇关于Spark SkinnableComponent skinDestructionPolicy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆