Händelseavlyssnare

Flash Player 9 och senare, Adobe AIR 1.0 och senare

Händelseavlyssnare, som även kallas händelsehanterare, är funktioner som Flash Player och AIR kör som svar på olika händelser. Du lägger till en händelseavlyssnare i två steg. Först skapar du en funktion eller klassmetod som Flash Player eller AIR ska köra som svar på en händelse. Detta kallas ibland för avlyssnarfunktionen eller händelsehanterarfunktionen. Sedan använder du metoden addEventListener() för att registrera avlyssnarfunktionen med målet för händelsen eller med något visningslisteobjekt som finns i lämpligt händelseflöde.

Skapa en avlyssnarfunktion

Sättet på vilket avlyssnarfunktioner skapas i ActionScript 3.0-händelsemodellen uppvisar vissa avvikelser från DOM-händelsemodellen. I DOM-händelsemodellen finns det en klar skillnad mellan en händelseavlyssnare och en avlyssnarfunktion: en händelseavlyssnare är en instans av en klass som implementerar EventListener-gränssnittet, medan en avlyssnarfunktion är en metod i den klassen med namnet handleEvent(). I DOM-händelsemodellen registrerar du klassinstansen som innehåller avlyssnarfunktionen snarare än den faktiska avlyssnarfunktionen.

I ActionScript 3.0-händelsemodellen är det ingen skillnad på en händelseavlyssnare och en avlyssnarfunktion. ActionScript 3.0 har inte något EventListener-gränssnitt, och avlyssnarfunktioner kan definieras utanför en klass eller som del av en klass. Dessutom behöver avlyssnarfunktioner inte heta handleEvent(). De kan namnges med valfri, giltig identifierare. I ActionScript 3.0 registrerar du namnet på den faktiska avlyssnarfunktionen.

Avlyssnarfunktion definierad utanför en klass

Nedanstående kod skapar en enkel SWF-fil som visar en röd kvadrat. En avlyssnare med namnet clickHandler(), som inte ingår i någon klass, lyssnar efter musklickningshändelser som sker i den röda rutan.

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

När en användare interagerar med den slutliga SWF-filen genom att klicka på rutan, genererar Flash Player eller AIR följande spårningsutdata:

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

Observera att händelseobjektet överförs som ett argument till clickHandler(). Detta gör att din avlyssnarfunktion kan undersöka händelseobjektet. I det här exemplet använder du händelseobjektets type-egenskap för att kontrollera om händelsen är en klickningshändelse.

Exemplet kontrollerar även värdet för nyckelordet this. I det här fallet representerar this det globala objektet, vilket är rimligt eftersom funktionen har definierats utanför en anpassad klass eller objekt.

Avlyssnarfunktion definierad som en klassmetod

Följande exempel är identiskt med föregående exempel som definierar klassen ClickExample, men här definieras funktionen clickHandler() som en metod i klassen ChildSprite:

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

När en användare interagerar med den slutliga SWF-filen genom att klicka på den röda rutan, genererar Flash Player eller AIR följande spårningsutdata:

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

Observera att nyckelordet this refererar till ChildSprite-instansen med namnet child. Detta beteende skiljer sig från det i ActionScript 2.0. Om du använde komponenter i ActionScript 2.0 kanske du kommer ihåg att när en klassmetod överfördes till UIEventDispatcher.addEventListener(), kopplades omfånget på metoden till komponenten som sände händelsen i stället för till klassen i vilken avlyssnarmetoden definierades. Så om du använde den här tekniken i ActionScript 2.0 skulle nyckelordet this referera till komponenten som sänder händelsen i stället för till ChildSprite-instansen.

Det här var till nackdel för vissa programmerare, eftersom det innebar att de inte kunde få tillgång till andra metoder eller egenskaper för klassen som innehöll avlyssnarmetoden. För att komma runt problemet kunde ActionScript 2.0-programmerare använda klassen mx.util.Delegate för att ändra omfånget på avlyssnarmetoden. Detta är nu inte längre nödvändigt, eftersom ActionScript 3.0 skapar en bunden metod när addEventListener() anropas. Det innebär att nyckelordet this refererar till ChildSprite-instansen med namnet child, och programmeraren får tillgång till de andra metoderna och egenskaperna i klassen ChildSprite.

Händelseavlyssnare som inte bör användas

Det finns en tredje teknik som kan användas för att skapa ett generiskt objekt med en egenskap som pekar på en dynamiskt tilldelad avlyssnarfunktion, men det här är inte en teknik som rekommenderas. Den beskrivs bara här för att den ofta användes i ActionScript 2.0. Den bör inte användas i ActionScript 3.0. Den här tekniken rekommenderas inte eftersom nyckelordet this kommer att referera till det globala objektet i stället för till avlyssnarobjektet.

Följande exempel är identiskt med föregående exempel från klassen ClickExample förutom att avlyssnarfunktionen definieras som en del av ett generiskt objekt med namnet 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); 
}

Resultatet av spårningen kommer att se ut så här:

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

Man skulle kunna tro att this refererar till myListenerObj och att spårningsutdata är [object Object], med det refererar i stället till det globala objektet. När du anger namnet på en dynamisk egenskap som argument till addEventListener(), kan Flash Player eller AIR inte skapa någon bunden metod. Det beror på att det du anger som listener-parameter inte är något annat än minnesadressen för avlyssnarfunktionen, och Flash Player och AIR kan inte länka den minnesadressen till myListenerObj-instansen.

Hantera händelseavlyssnare

Du kan hantera dina avlyssnarfunktioner med hjälp av metoderna för IEventDispatcher-gränssnittet. IEventDispatcher-gränssnittet är ActionScript 3.0-versionen av EventTarget-gränssnittet i DOM-händelsemodellen. Även om namnet IEventDispatcher verkar antyda att dess främsta funktion är att skicka händelseobjekt, används metoderna i den här klassen faktiskt mer för att registrera, kontrollera och ta bort händelseavlyssnare. IEventDispatcher-gränssnittet definierar fem metoder, som i följande kod:

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

Flash Player API implementerar IEventDispatcher-gränssnittet med klassen EventDispatcher, som fungerar som basklass för alla klasser som kan vara händelsemål eller del av ett händelseflöde. Klassen DisplayObject ärver till exempel från klassen EventDispatcher. Det innebär att objekt i visningslistan har tillgång till metoderna i IEventDispatcher-gränssnittet.

Lägga till händelseavlyssnare

addEventListener()-metoden är arbetshästen hos IEventDispatcher-gränssnittet. Du använder den för att registrera avlyssnarfunktioner. De två parametrarna som krävs är type och listener. Du använder parametern type för att ange typen av händelse. Du använder parametern listener för att ange avlyssnarfunktionen som ska köras när händelsen inträffar. Parametern listener kan vara en referens till antingen en funktion eller en klassmetod.

Använd inte parenteser när du anger listener-parametern. Funktionen clickHandler() anges till exempel utan parentes i följande anrop till addEventListener()-metoden:
addEventListener(MouseEvent.CLICK, clickHandler)

Parametern useCapture för metoden addEventListener() gör att du kan styra händelseflödesfasen som avlyssnaren ska vara aktiv för. Om useCapture är true kommer avlyssnaren att vara aktiv under händelseflödets hämtningsfas. Om useCapture är false kommer avlyssnaren att vara aktiv under händelseflödets målfas och bubblingsfas. Om du vill lyssna efter en händelse under händelseflödets alla tre faser måste du anropa addEventListener() två gånger, en gång med useCapture inställd på true och sedan en gång till med useCapture inställd på false.

Parametern priority för metoden addEventListener() är inte en officiell del av DOM Level 3-händelsemodellen. Den ingår i ActionScript 3.0 för att du på ett mer flexibelt sätt ska kunna hantera dina händelseavlyssnare. När du anropar addEventListener() kan du ställa in prioriteten för den händelseavlyssnaren genom att ange ett heltalsvärde som priority-parameter. Standardvärdet är 0, men du kan ställa in den på negativa eller positiva heltalsvärden. Ju högre värde, desto tidigare kommer händelseavlyssnaren att köras. Händelseavlyssnare som har samma prioritet körs i den ordning de infogades, så ju tidigare en avlyssnare läggs till, desto tidigare kommer den att köras.

Parametern useWeakReference gör att du kan ange om referensen till avlyssnarfunktionen är svag eller normal. Om du ställer in den här parametern på true kan du undvika situationer där avlyssnarfunktioner finns kvar i minnet även när de inte längre behövs. Flash Player och AIR använder en teknik som kallas skräpsamling för att rensa de objekt från minnet som inte längre används. Ett objekt anses inte längre vara i bruk om det inte finns någon referens till objektet. Skräpsamlingen ignorerar svaga referenser, vilket innebär att en avlyssnarfunktion som bara har en svag referenspunkt som pekar på den kvalificerar sig för skräpsamling.

Ta bort händelseavlyssnare

Du kan använda metoden removeEventListener() när du vill ta bort en händelseavlyssnare som inte längre behövs. Det kan vara en bra idé att ta bort avlyssnare som inte längre används. Obligatoriska parametrar omfattar parametrarna eventName och listener, som är desamma som de parametrar som krävs för metoden addEventListener(). Kom ihåg att du kan lyssna efter händelser under alla händelsefaser genom att anropa addEventListener() två gånger, en gång med useCapture inställd på true och sedan en gång till inställd på false. Om du vill ta bort båda händelseavlyssnarna måste du anropa removeEventListener() två gånger, först med useCapture inställd på true och sedan en gång till inställd på false.

Skicka händelser

Metoden dispatchEvent() kan användas av erfarna programmerare för att skicka ett anpassat händelseobjekt till händelseflödet. Den enda parametern som godtas av den här metoden är en referens till ett händelseobjekt, som måste vara en instans av klassen Event eller en underklass till klassen Event. Efter att ha skickats ställs egenskapen target för händelseobjektet in på objektet där dispatchEvent() anropades.

Söka efter befintliga händelseavlyssnare

De sista två metoderna i IEventDispatcher-gränssnittet erbjuder användbar information om förekomsten av händelseavlyssnare. Metoden hasEventListener() returnerar true om en händelseavlyssnare påträffas för en specifik händelsetyp i ett visst visningslisteobjekt. Metoden willTrigger() returnerar även true om en avlyssnare påträffas för ett visst visningslisteobjekt, men willTrigger() söker inte bara efter avlyssnare som finns i det visningsobjektet utan i alla visningsobjektets indirekta överordnade för alla faser av händelseflödet.

Felhändelser utan avlyssnare

Undantag, snarare än händelser, är den primära mekanismen för felhantering i ActionScript 3.0, men undantagshantering fungerar inte för asynkrona åtgärder som inläsning av filer. Om ett fel uppstår under en asynkron åtgärd skickar Flash Player och AIR ett felhändelseobjekt. Om du inte skapar en avlyssnare för den felhändelsen, kommer felsökningsversionerna av Flash Player och AIR att visa en dialogruta med information om felet. Felsökningsversionen av Flash Player skapar till exempel följande dialogruta som beskriver felet när programmet försöker att läsa in en fil från en ogiltig URL:

De flesta felhändelser är baserade på klassen ErrorEvent och som sådana har de en egenskap med namnet text som används för att lagra felmeddelandet som Flash Player eller AIR visar. De två undantagen är klasserna StatusEvent och NetStatusEvent. Båda dessa klasser har en level-egenskap (StatusEvent.level och NetStatusEvent.info.level). När värdet för level-egenskapen är error, betraktas dessa händelsetyper som felhändelser.

En felhändelse medför inte att körningen av en SWF-fil avbryts. Den visar sig bara i form av en dialogruta i felsökningsversioner av webbläsarplugin-program och fristående spelare, som ett meddelande i utdatapanelen i utvecklingsspelaren och som en post i loggfilen för Adobe Flash Builder. Den visas inte alls i de officiella versionerna av Flash Player eller AIR.