Spark SkinnableComponent skinDestructionPolicy - PullRequest
2 голосов
/ 16 ноября 2011

В рамках попытки устранения утечки памяти в нашем приложении мы обнаружили, что для каждого 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 способа обойти это поведение кажется мне довольно странным. Документация по этому вопросу также недостаточна, поэтому любые идеи будут очень кстати.

Приветствия

1 Ответ

2 голосов
/ 07 января 2012

По моему опыту, использование пространства имен mx::internal в Flex SDK обычно означает что-то вроде: «Вы можете использовать эту функциональность, если вы знаете, что делаете, а такжемы (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" рядом.

...