Gebeurtenislisteners

Flash Player 9 of hoger, Adobe AIR 1.0 of hoger

Gebeurtenislisteners, die ook gebeurtenishandlers worden genoemd, zijn functies die door Flash Player en AIR worden uitgevoerd als reactie op specifieke gebeurtenissen. Het toevoegen van een gebeurtenislistener bestaat uit twee stappen. Eerst maakt u een functie of een klassenmethode die door Flash Player of AIR kan worden uitgevoerd als reactie op de gebeurtenis. Dit wordt soms de listenerfunctie of gebeurtenishandlerfunctie genoemd. Vervolgens gebruikt u de methode addEventListener() om de listenerfunctie te registreren bij het doel van de gebeurtenis of bij een willekeurig weergaveoverzichtobject dat in de juiste gebeurtenisstroom ligt.

Een listenerfunctie maken

Het maken van listenerfuncties is één gebied waarop het ActionScript 3.0-gebeurtenismodel afwijkt van het DOM-gebeurtenismodel. In het DOM-gebeurtenismodel is een duidelijk verschil tussen een gebeurtenislistener en een listenerfunctie: een gebeurtenislistener is een instantie van een klasse die de interface EventListener implementeert, terwijl een listenerfunctie een methode van die klasse met de naam handleEvent() is. In het DOM-gebeurtenismodel registreert u de klasseninstantie die de listenerfunctie bevat en niet de eigenlijke listenerfunctie.

In het ActionScript 3.0-gebeurtenismodel bestaat er geen onderscheid tussen een gebeurtenislistener en een listenerfunctie: ActionScript 3.0 kent geen interface EventListener en listenerfuncties kunnen buiten een klasse of als deel van een klasse worden gedefinieerd. Verder hoeven listenerfuncties niet handleEvent() te worden genoemd. Elke geldige naam is toegestaan. In ActionScript 3.0 registreert u de naam van de feitelijke listenerfunctie.

Listenerfunctie die buiten een klasse is gedefinieerd

Met de volgende code wordt een eenvoudig SWF-bestand gemaakt waarmee een rood vierkant wordt weergegeven. Een listenerfunctie met de naam clickHandler(), die geen deel uitmaakt van een klasse, luistert naar muisklikgebeurtenissen op het rode vierkant.

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, clickHandler); 
    } 
} 
 
function clickHandler(event:MouseEvent):void 
{ 
    trace("clickHandler detected an event of type: " + event.type); 
    trace("the this keyword refers to: " + this); 
}

Wanneer een gebruiker met het resulterende SWF-bestand communiceert door op het vierkant te klikken, genereert Flash Player of AIR de volgende trace-uitvoer:

clickHandler detected an event of type: click 
the this keyword refers to: [object global]

Het gebeurtenisobject wordt als argument doorgegeven aan clickHandler(). Hierdoor kan het gebeurtenisobject door de listenerfunctie worden gecontroleerd. In dit voorbeeld gebruikt u de eigenschap type van het gebeurtenisobject om te controleren of de gebeurtenis een klikgebeurtenis is.

In het voorbeeld wordt ook de waarde van het trefwoord this gecontroleerd. In dit geval vertegenwoordigt this het algemene object. Dit is logisch, omdat de functie buiten enige aangepaste klasse of enig aangepast object is gedefinieerd.

Listenerfunctie die als klassenmethode is gedefinieerd

Het volgende voorbeeld is gelijk aan het vorige ClickExample-voorbeeld, met het verschil dat de functie clickHandler() als een methode van de klasse ChildSprite is gedefinieerd:

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, clickHandler); 
    } 
    private function clickHandler(event:MouseEvent):void 
    { 
        trace("clickHandler detected an event of type: " + event.type); 
        trace("the this keyword refers to: " + this); 
    } 
}

Wanneer een gebruiker met het resulterende SWF-bestand communiceert door op het rode vierkant te klikken, genereert Flash Player of AIR de volgende trace-uitvoer:

clickHandler detected an event of type: click 
the this keyword refers to: [object ChildSprite]

Het trefwoord this verwijst naar de ChildSprite-instantie met de naam child. Dit gedrag wijkt af van het gedrag in ActionScript 2.0. Als u componenten gebruikte in ActionScript 2.0, weet u wellicht nog wel dat wanneer een klassenmethode werd doorgegeven aan UIEventDispatcher.addEventListener(), het bereik van de methode was gekoppeld aan de component waardoor de gebeurtenis werd verzonden en niet aan de klasse waarin de listenermethode werd gedefinieerd. Met andere woorden, als u deze techniek in ActionScript 2.0 gebruikte, verwees het trefwoord this naar de component die de gebeurtenis verzond en niet naar de ChildSprite-instantie.

Dit kon een serieus probleem voor sommige programmeurs zijn, omdat dit betekende dat deze geen toegang hadden tot andere methoden en eigenschappen van de klasse waarin de listenermethode werd gedefinieerd. Als oplossing konden ActionScript 2.0-programmeurs de klasse mx.util.Delegate gebruiken om het bereik van de listenermethode te wijzigen. Dit is echter niet meer nodig, omdat ActionScript 3.0 een gekoppelde methode maakt wanneer addEventListener() wordt aangeroepen. Als gevolg hiervan verwijst het trefwoord this naar de ChildSprite-instantie met de naam child en heeft de programmeur toegang tot de andere methoden en eigenschappen van de klasse ChildSprite.

Gebeurtenislistener waarvan het gebruik wordt afgeraden

Er bestaat een derde techniek waarbij u een algemeen object maakt met een eigenschap die verwijst naar een dynamisch toegewezen listenerfunctie. Het gebruik hiervan wordt echter niet aanbevolen. Deze techniek wordt hier besproken, omdat deze veel werd gebruikt in ActionScript 2.0, maar in ActionScript 3.0 beter niet gebruikt kan worden. Deze techniek wordt afgeraden omdat het trefwoord this naar het algemene object verwijst en niet naar het listenerobject.

Het volgende voorbeeld is gelijk aan het vorige ClickExample-voorbeeld, met het verschil dat de listenerfunctie is gedefinieerd als deel van een algemeen object met de naam myListenerObj:

package 
{ 
    import flash.display.Sprite; 
 
    public class ClickExample extends Sprite 
    { 
        public function ClickExample() 
        { 
            var child:ChildSprite = new ChildSprite(); 
            addChild(child); 
        } 
    } 
} 
 
import flash.display.Sprite; 
import flash.events.MouseEvent; 
 
class ChildSprite extends Sprite 
{ 
    public function ChildSprite() 
    { 
        graphics.beginFill(0xFF0000); 
        graphics.drawRect(0,0,100,100); 
        graphics.endFill(); 
        addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler); 
    } 
} 
 
var myListenerObj:Object = new Object(); 
myListenerObj.clickHandler = function (event:MouseEvent):void 
{ 
        trace("clickHandler detected an event of type: " + event.type); 
        trace("the this keyword refers to: " + this); 
}

De resultaten van de trace zien er als volgt uit:

clickHandler detected an event of type: click 
the this keyword refers to: [object global]

Men zou verwachten dat this naar myListenerObj verwijst en dat de trace-uitvoer [object Object] is. Dit is echter niet het geval, this verwijst naar het algemene object. Wanneer u de naam van een dynamische eigenschap als argument doorgeeft aan addEventListener(), kan Flash Player of AIR geen gekoppelde methode maken. De reden hiervoor is dat u als parameter listener slechts het geheugenadres van de listenerfunctie doorgeeft en dat Flash Player en AIR dit geheugenadres op geen enkele manier kunnen koppelen aan de instantie myListenerObj.

Gebeurtenislisteners beheren

U kunt listenerfuncties beheren met behulp van de methoden van de interface IEventDispatcher. De interface IEventDispatcher is de ActionScript 3.0-versie van de interface EventTarget van het DOM-gebeurtenismodel. Hoewel de naam IEventDispatcher lijkt te impliceren dat het hoofddoel het verzenden van gebeurtenisobjecten is, worden de methoden van deze klasse veel vaker gebruikt voor het registreren van, controleren op en verwijderen van gebeurtenislisteners. De interface IEventDispatcher definieert vijf methoden, zoals in de volgende code wordt weergegeven:

package flash.events 
{ 
    public interface IEventDispatcher 
    { 
        function addEventListener(eventName:String,  
                        listener:Object, 
                        useCapture:Boolean=false, 
                        priority:Integer=0, 
                        useWeakReference:Boolean=false):Boolean; 
 
        function removeEventListener(eventName:String,  
                    listener:Object, 
                    useCapture:Boolean=false):Boolean; 
 
        function dispatchEvent(eventObject:Event):Boolean; 
 
        function hasEventListener(eventName:String):Boolean; 
        function willTrigger(eventName:String):Boolean; 
    } 
}

De Flash Player-API implementeert de interface IEventDispatcher met de klasse EventDispatcher, die als basisklasse fungeert voor alle klassen die gebeurtenisdoelen of onderdelen van een gebeurtenisstroom kunnen zijn. De klasse DisplayObject overerft bijvoorbeeld van de klasse EventDispatcher. Dit betekent dat elk object op het weergaveoverzicht toegang heeft tot de methoden van de interface IEventDispatcher.

Gebeurtenislisteners toevoegen

De methode addEventListener() is het werkpaard van de interface IEventDispatcher. U gebruikt deze voor het registreren van de listenerfuncties. De twee vereiste parameters zijn type en listener. U gebruikt de parameter type om het type gebeurtenis op te geven. U gebruikt de parameter listener om op te geven welke listenerfunctie wordt uitgevoerd wanneer de gebeurtenis plaatsvindt. De parameter listener kan een verwijzing zijn naar een functie of naar een klassenmethode.

Gebruik geen haakjes bij het opgeven van de parameter listener. De functie clickHandler() wordt bijvoorbeeld zonder haakjes opgegeven in de volgende aanroep van de methode addEventListener():
addEventListener(MouseEvent.CLICK, clickHandler)

Met de parameter useCapture van de methode addEventListener() kunt u controleren in welke fase van de gebeurtenisstroom de listener actief wordt. Als useCapture op true is ingesteld, wordt de listener actief tijdens de vastlegfase van de gebeurtenisstroom. Als useCapture op false is ingesteld, wordt de listener actief tijdens de doel- en terugkoppelfasen van de gebeurtenisstroom. Wanneer u in alle drie fasen naar de gebeurtenis wilt luisteren, roept u addEventListener() tweemaal aan, één keer met useCapture ingesteld op true en één keer met useCapture ingesteld op false.

De parameter priority van de methode addEventListener() maakt niet officieel deel uit van het DOM Level 3-gebeurtenismodel. Het is opgenomen in ActionScript 3.0 om u meer flexibiliteit te bieden bij het indelen van de gebeurtenislisteners. Wanneer u addEventListener() aanroept, kunt u de prioriteit voor die gebeurtenislistener instellen door een geheel-getalwaarde als parameter priority door te geven. De standaardwaarde is 0, maar u kunt deze wijzigen in een negatieve of positieve geheel-getalwaarde. Hoe hoger het getal, des te sneller die gebeurtenislistener wordt uitgevoerd. Gebeurtenislisteners met dezelfde prioriteit worden uitgevoerd in de volgorde waarin deze zijn toegevoegd. Hoe eerder een listener wordt toegevoegd, des te sneller deze wordt uitgevoerd.

Met de parameter useWeakReference kunt u opgeven of de verwijzing naar de listenerfunctie zwak of normaal is. Als u deze parameter op true instelt, kunt u situaties vermijden waarbij listenerfuncties in het geheugen aanwezig blijven, terwijl deze niet meer vereist zijn. Flash Player en AIR maken gebruik van een techniek voor het verwijderen van objecten uit het geheugen die niet meer in gebruik zijn. Deze techniek wordt opschonen genoemd. Een object is niet meer in gebruik als er geen verwijzingen naar bestaan. De opschoonfunctie negeert zwakke verwijzingen. Dit betekent dat als er alleen een zwakke verwijzing naar een listenerfunctie bestaat, de listenerfunctie in aanmerking komt voor opschonen.

Gebeurtenislisteners verwijderen

U kunt de methode removeEventListener() gebruiken om een gebeurtenislistener te verwijderen die u niet meer nodig hebt. Het is raadzaam om alle listeners die niet meer worden gebruikt, te verwijderen. Vereiste parameters zijn onder meer de parameters eventName en listener. Dit zijn dezelfde vereiste parameters als voor de methode addEventListener(). U kunt tijdens alle gebeurtenisfasen naar gebeurtenissen luisteren door addEventListener() tweemaal aan te roepen, één keer met useCapture ingesteld op true en één keer met deze parameter ingesteld op false. Als u beide gebeurtenislisteners wilt verwijderen, roept u removeEventListener() tweemaal aan, één keer met useCapture ingesteld op true en één keer met deze parameter ingesteld op false.

Gebeurtenissen verzenden

De methode dispatchEvent() kan door gevorderde programmeurs worden gebruikt om een aangepast gebeurtenisobject naar de gebeurtenisstroom te verzenden. De enige parameter die door deze methode wordt geaccepteerd, is een verwijzing naar een gebeurtenisobject, dat een instantie moet zijn van de klasse Event of van een subklasse van de klasse Event. Als de gebeurtenis is verzonden, wordt de eigenschap target van het gebeurtenisobject ingesteld op het object waarop dispatchEvent() was aangeroepen.

Controleren op bestaande gebeurtenislisteners

De laatste twee methoden van de interface IEventDispatcher bevatten nuttige informatie over het bestaan van gebeurtenislisteners. De methode hasEventListener() retourneert true als er een gebeurtenislistener is gevonden voor een specifiek gebeurtenistype op een bepaald weergaveoverzichtobject. De methode willTrigger() retourneert ook true als er een listener is gevonden voor een bepaald weergaveobject, maar willTrigger() zoekt niet alleen naar listeners op dat weergaveobject, maar ook naar listeners op alle voorouders van dat weergaveoverzichtobject voor alle fasen van de gebeurtenisstroom.

Foutgebeurtenissen zonder listeners

Uitzonderingen, en niet gebeurtenissen, vormen het belangrijkste mechanisme voor foutafhandeling in ActionScript 3.0. Foutafhandeling werkt echter niet voor asynchrone bewerkingen zoals het laden van bestanden. Als tijdens een dergelijke asynchrone bewerking een fout optreedt, verzenden Flash Player en AIR een foutgebeurtenisobject. Als u geen listener voor de foutgebeurtenis maakt, wordt door de foutopsporingsversies van Flash Player en AIR een dialoogvenster weergegeven met informatie over de fout. Zo genereert de foutopsporingsversie van Flash Player het volgende dialoogvenster waarin de fout wordt beschreven wanneer de toepassing een bestand vanaf een ongeldige URL probeert te laden:

De meeste foutgebeurtenissen zijn gebaseerd op de klasse ErrorEvent en hebben als zodanig een eigenschap met de naam text, waarmee het foutbericht wordt opgeslagen dat door Flash Player of AIR wordt weergegeven. De twee uitzonderingen zijn de klassen StatusEvent en NetStatusEvent. Deze klassen hebben een eigenschap level (StatusEvent.level en NetStatusEvent.info.level). Wanneer de waarde van de eigenschap level gelijk is aan "error", worden deze gebeurtenistypen als foutgebeurtenissen beschouwd.

Een foutgebeurtenis zorgt er niet voor dat de uitvoering van een SWF-bestand wordt afgesloten. Deze wordt alleen weergegeven als een dialoogvenster in de foutopsporingsversies van de insteekmodules van de browser en zelfstandige spelers, als een bericht in het uitvoervenster in de oorspronkelijke speler en als een item in het logbestand voor Adobe Flash Builder. In de releaseversies van Flash Player of AIR levert een foutgebeurtenis geen enkele melding op.