ItemRenderer: ab-/anmelden von EventListenern

Viele Beispiele im Netz zeigen, wie schnell und einfach sich ItemRenderer für Flex-Komponenten erstellen lassen. Leider sind diese Beispiele für größere Anwendungen kaum zu gebrauchen, da entweder die Performance durch die vielen Bindings verloren geht, oder verwendete EventListener nicht mehr abgemeldet werden.

Aber wann ist nun der richtige Zeitpunkt um EventListener in ItemRenderern wieder abzumelden? Da die meisten Flex-Komponenten die Renderer intern wiederverwenden (es wird lediglich die data-Eigenschaft des Renderers geändert), besteht die Möglichkeit bei Änderungen dieser Eigenschaft die Listener abzumelden.

private var _dataChanged:Boolean;

    /**
     * @inheritDoc
     */
    override public function set data(value:Object):void {
        if (data != value) {
            if (data) {
                removeDataListener();
            }
            super.data = value;
            _dataChanged = true;
            invalidateProperties();
        }
    }

    /**
     * @inheritDoc
     */
    override protected function commitProperties():void {
        super.commitProperties();

        if (_dataChanged) {
            _dataChanged = false;
            if (data) {
                addDataListener();
                // do other stuff here
            }
        }
    }

    protected function removeDataListener():void {
        // remove data listener
    }

    protected function addDataListener():void {
        // add data listener
    }

Leider ist dies nur die halbe Miete. Was passiert wenn die Flex-Komponente, die die Renderer verwendet, oder der Renderer selbst aus der DisplayList entfernt wird? Es existieren immer noch die Listener innerhalb des Renderers, der dadurch vor der GarbageCollection (GC) geschützt wird. Dies betrifft nur Listener die nicht als weak-Listener angemeldet wurden.

Aus diesem Grund melden wir uns für das Event “REMOVED_FROM_STAGE” an und sorgen dafür, dass alle Listener abgemeldet werden. Lediglich der Listener für das Event “REMOVED_FROM_STAGE” bleibt bestehen, da es vorkommen kann, dass eine Flex-Komponente ihre Renderer aus der DisplayList nimmt und später wiederverwendet. Der Renderer wird trotz des “REMOVED_FROM_STAGE”-Listeners von der GC entfernt, da dieser als weak-Listener angemeldet wurde.

package {

import flash.events.Event;
import mx.core.EventPriority;
import spark.components.supportClasses.ItemRenderer;

public class BaseItemRenderer extends ItemRenderer {

    private var _dataChanged:Boolean;

    /**
     * Constructor.
     */
    public function BaseItemRenderer() {
        addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage, false, EventPriority.DEFAULT, true);
    }

    /**
     * @inheritDoc
     */
    override public function set data(value:Object):void {
        if (data != value) {
            if (data) {
                removeDataListener();
            }
            super.data = value;
            _dataChanged = true;
            invalidateProperties();
        }
    }

    /**
     * @inheritDoc
     */
    override protected function commitProperties():void {
        super.commitProperties();

        if (_dataChanged) {
            _dataChanged = false;
            if (data) {
                addDataListener();
                // do other stuff here
            }
        }
    }

    // Should be used to free all unused data.
    protected function dispose():void {
        data = null;
        // do other stuff here
    }

    protected function removeDataListener():void {
        // remove data listener
    }

    protected function addDataListener():void {
        // add data listener
    }

    private function onRemovedFromStage(event:Event):void {
        dispose();
    }
}
}

Die endgültige Version des hier vorgestellten ItemRenderers könnt ihr hier herunterladen.

This entry was posted in Actionscript, Flex and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>