I listener di eventi, detti anche gestori di eventi, sono funzioni che Flash Player e AIR eseguono in risposta a eventi specifici. L'aggiunta di un listener di eventi è una procedura che si compone di due fasi. Create per prima cosa una funzione o un metodo di classe che Flash Player o AIR devono eseguire in risposta all'evento. Questa funzione viene talvolta definita come funzione listener o funzione gestore di eventi. In secondo luogo, usate il metodo
addEventListener()
per associare alla funzione listener il destinatario dell'evento o un oggetto dell'elenco di visualizzazione che appartiene al flusso di eventi appropriato.
Creazione di una funzione listener
La creazione di funzioni listener è un ambito in cui il modello eventi di ActionScript 3.0 si discosta dal modello eventi DOM. Nel modello eventi DOM, esiste una distinzione netta tra un listener di eventi e una funzione listener: un listener di eventi è un'istanza di una classe che implementa l'interfaccia EventListener, mentre la funzione listener è un metodo di quella classe definito
handleEvent()
. Nel modello eventi DOM è necessario registrare l'istanza della classe che contiene la funzione listener e non la funzione listener in sé.
Nel modello eventi di ActionScript 3.0 non esiste una distinzione tra un listener di eventi e una funzione listener. ActionScript 3.0 non dispone dell'interfaccia EventListener e le funzioni listener possono essere definite al di fuori di una classe o come parte di una classe. Inoltre, le funzioni listener non devono necessariamente chiamarsi
handleEvent()
in quanto possono essere definite tramite un qualsiasi identificatore valido. In ActionScript 3.0, è necessario registrare il nome della funzione listener.
Funzione listener definita al di fuori di una classe
L'esempio di codice seguente crea un file SWF semplice in cui viene visualizzato un quadrato rosso. La funzione listener
clickHandler()
, che non fa parte di una classe, monitora gli eventi click del mouse sul quadrato rosso.
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);
}
Quando un utente interagisce con il file SWF facendo clic sul quadrato, Flash Player o AIR generano il seguente output di traccia:
clickHandler detected an event of type: click
the this keyword refers to: [object global]
Notate che l'oggetto evento viene passato come argomento a
clickHandler()
. Questo permette alla funzione listener di analizzare l'oggetto evento. In questo esempio, è necessario usare la proprietà
type
dell'oggetto evento per determinare se l'evento è un clic del mouse.
L'esempio verifica anche il valore della parola chiave
this
. In questo caso,
this
rappresenta l'oggetto globale; questo è opportuno perché la funzione è definita al di fuori di qualsiasi classe predefinita o oggetto.
Funzione listener definita come metodo di classe
L'esempio seguente è identico a quello precedente che definisce la classe ClickExample, con la sola eccezione che la funzione
clickHandler()
è definita come metodo della classe 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);
}
}
Quando un utente interagisce con il file SWF facendo clic sul quadrato rosso, Flash Player o AIR generano il seguente output di traccia:
clickHandler detected an event of type: click
the this keyword refers to: [object ChildSprite]
Notate che la parola chiave
this
si riferisce all'istanza di ChildSprite denominata
child
. Questo rappresenta un cambiamento rispetto a quanto avviene in ActionScript 2.0. Chi ha dimestichezza con i componenti in ActionScript 2.0 ricorderà che quando un metodo di classe viene passato a
UIEventDispatcher.addEventListener()
, l'area di validità del metodo è legata al componente che ha trasmesso l'evento anziché alla classe in cui il metodo listener è stato definito. In altre parole, usando questa tecnica in ActionScript 2.0, la parola chiave
this
farebbe riferimento al componente che trasmette l'evento anziché all'istanza di ChildSprite.
Questo rappresenta un problema notevole per i programmatori perché significa che non possono accedere ad altri metodi e proprietà della classe che contiene il metodo listener. Per aggirare il problema, i programmatori di ActionScript 2.0 potevano usare la classe
mx.util.Delegate
per cambiare l'area di validità del metodo listener. Questo espediente non è tuttavia più necessario perché ActionScript 3.0 crea un metodo vincolato quando viene chiamato
addEventListener()
. Di conseguenza, la parola chiave
this
fa riferimento all'istanza di ChildSprite denominata
child
e il programmatore ha accesso agli altri metodi e alle proprietà della classe ChildSprite.
Listener di eventi da evitare
Esiste una terza possibilità, sconsigliata, che consiste nel creare un oggetto generico dotato di una proprietà che punta a una funzione listener assegnata in modo dinamico. Questa tecnica viene comunque presentata qui perché era usata comunemente in ActionScript 2.0, ma se ne sconsiglia l'impiego in ActionScript 3.0, in quanto la parola chiave
this
farebbe riferimento all'oggetto globale e non all'oggetto listener.
L'esempio che segue è identico all'esempio precedente della classe ClickExample, con l'eccezione che qui la funzione listener è definita come parte di un oggetto generico denominato
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);
}
Il risultato dell'output di traccia è il seguente:
clickHandler detected an event of type: click
the this keyword refers to: [object global]
In questo caso
this
fa riferimento all'oggetto globale e non a
myListenerObj
e l'output di traccia non è
[object Object]
. Quando passate il nome di una proprietà dinamica come argomento a
addEventListener()
, Flash Player o AIR non è in grado di creare un metodo vincolato perché il parametro passato come
listener
non è altro che l'indirizzo di memoria della funzione listener e Flash Player e AIR non hanno modo di collegare quell'indirizzo all'istanza di
myListenerObj
.
Gestione dei listener di eventi
È possibile gestire le funzioni listener usando i metodi dell'interfaccia IEventDispatcher. IEventDispatcher è la versione di ActionScript 3.0 dell'interfaccia EventTarget del modello eventi DOM. Nonostante il nome IEventDispatcher sembri sottintendere che il suo scopo principale sia inviare (in inglese “dispatch”) oggetti evento, in realtà, i metodi di questa classe sono usati in prevalenza per registrare i listener di eventi, verificare la presenza di listener di eventi e rimuovere i listener di eventi. L'interfaccia IEventDispatcher definisce cinque metodi, come illustrato nel codice seguente:
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;
}
}
L'API Flash Player implementa l'interfaccia IEventDispatcher con la classe EventDispatcher, che funge da classe base per tutte le classi suscettibili di essere destinatarie di eventi o parte del flusso di eventi. La classe DisplayObject, ad esempio, eredita dalla classe EventDispatcher. Ciò significa che qualsiasi oggetto dell'elenco di visualizzazione ha accesso ai metodi dell'interfaccia IEventDispatcher.
Aggiunta dei listener di eventi
Il metodo
addEventListener()
è il pezzo forte dell'interfaccia IEventDispatcher e consente di registrare le funzioni listener. I due parametri obbligatori sono
type
e
listener
. Con il parametro
type
specificate il tipo di evento, mentre con il parametro
listener
specificate la funzione listener da eseguire quando si verifica l'evento. Il parametro
listener
può essere un riferimento a una funzione o a un metodo di classe.
non utilizzate le parentesi per specificare il parametro
listener
. La funzione
clickHandler()
, ad esempio, è specificata senza parentesi nella seguente chiamata al metodo
addEventListener()
:
addEventListener(MouseEvent.CLICK, clickHandler)
Il parametro
useCapture
del metodo
addEventListener()
consente di controllare la fase del flusso di eventi in cui il listener sarà attivo. Se
useCapture
è impostato su
true
, il listener sarà attivo durante la fase di cattura del flusso di eventi. Se
useCapture
è impostato su
false
, il listener sarà attivo durante la fase target e di bubbling del flusso di eventi. Per monitorare un evento durante tutte le fasi del flusso di eventi, chiamate
addEventListener()
due volte, una volta con
useCapture
impostato su
true
e una seconda volta con
useCapture
impostato su
false
.
Il parametro
priority
del metodo
addEventListener()
non è un elemento ufficiale del modello eventi DOM Level 3, però è stato incluso in ActionScript 3.0 per rendere più flessibile l'organizzazione dei listener di eventi. Quando chiamate
addEventListener()
, potete impostare la priorità per quel listener di eventi passando un valore intero come parametro
priority
. Il valore predefinito è 0, ma è possibile modificarlo in un valore intero negativo o positivo. Più è alto il numero, prima verrà eseguito il listener di eventi. I listener di eventi con la stessa priorità vengono eseguiti nell'ordine in cui sono stati aggiunti, quindi prima è stato aggiunto un listener, prima viene eseguito.
Il parametro
useWeakReference
permette di specificare se il riferimento alla funzione listener è debole o normale. Impostando questo parametro su
true
è possibile evitare situazioni in cui le funzioni listener rimangono in memoria anche quando diventano superflue. Flash Player e AIR usano la tecnica
garbage collection
per eliminare dalla memoria gli oggetti inutilizzati. Un oggetto viene considerato inutilizzato quando non esistono più riferimenti ad esso. L'operazione di garbage collection non tiene in considerazione i riferimenti deboli, vale a dire che una funzione listener per cui esiste solo un riferimento debole diventa una candidata per la garbage collection.
Eliminazione dei listener di eventi
Per rimuovere i listener di eventi inutilizzati si può usare il metodo
removeEventListener()
. È buona norma rimuovere i listener diventati superflui. I parametri obbligatori sono
eventName
e
listener
, cioè gli stessi parametri del metodo
addEventListener()
. Ricordate che potete monitorare gli eventi durante tutte le fasi del flusso di eventi chiamando due volte
addEventListener()
: una con
useCapture
impostato su
true
e una seconda con il parametro impostato su
false
. Per eliminare entrambi i listener di eventi dovete chiamare
removeEventListener()
due volte: una prima volta con
useCapture
impostato su
true
e una seconda volta con il parametro impostato su
false
.
Invio degli eventi
I programmatori esperti possono usare il metodo
dispatchEvent()
per inviare un oggetto evento personalizzato nel flusso di eventi. L'unico parametro accettato da questo metodo è un riferimento a un oggetto evento, che deve essere un'istanza o una sottoclasse della classe Event. Una volta inviato l'evento, la proprietà
target
dell'oggetto evento viene impostata sull'oggetto su cui il metodo
dispatchEvent()
è stato chiamato.
Verifica della presenza di listener di eventi
Gli ultimi due metodi dell'interfaccia IEventDispatcher forniscono informazioni utili per individuare l'esistenza di listener di eventi. Il metodo
hasEventListener()
restituisce il valore
true
se individua un listener di eventi per un tipo di evento specifico su un particolare oggetto dell'elenco di visualizzazione. Anche il metodo
willTrigger()
restituisce il valore
true
se individua un listener per un oggetto specifico dell'elenco di visualizzazione, ma
willTrigger()
verifica la presenza di listener non solo sull'oggetto di visualizzazione in sé ma anche su tutti gli antenati dell'oggetto per tutte le fasi del flusso di eventi.
Eventi errore senza listener
Sono le eccezioni, e non gli eventi, il meccanismo principale per la gestione degli errori in ActionScript 3.0, ma la gestione delle eccezioni non prende in considerazione le operazioni asincrone come il caricamento dei file. Se si verifica un errore durante un'operazione asincrona di questo tipo, Flash Player e AIR inviano un oggetto evento errore. Se non create un listener per gli eventi errore, le versioni debugger di Flash Player e AIR chiamano una finestra di dialogo con alcune informazioni sull'errore. La versione del debugger di Flash Player, ad esempio, quando l'applicazione prova a caricare un file da un URL non valido visualizza le seguenti finestre di dialogo che descrivono l'errore:
La maggior parte degli eventi errore si basa sulla classe ErrorEvent e in quanto tali sono configurati con la proprietà
text
che viene utilizzata per memorizzare il messaggio di errore visualizzato da Flash Player o AIR. Le uniche due eccezioni sono costituite dalle classi StatusEvent e NetStatusEvent, che sono caratterizzate dalla proprietà
level
(
StatusEvent.level
e
NetStatusEvent.info.level
). Quando il valore della proprietà
level
è "
error
", questi tipi di evento vengono considerati eventi errore.
Un evento errore non determina l'arresto della riproduzione di un file SWF e genera solo la visualizzazione di una finestra di dialogo nelle versioni debugger dei plug-in per browser e dei lettori autonomi, di un messaggio nel pannello Output nel player di creazione e l'aggiunta di una riga nel file di registro di Adobe Flash Builder. Non si manifesta affatto nelle versioni standard di Flash Player o AIR.
|
|
|