Flash CS3 - Flash CS4

Free tutorials and scripts for all.
Actionscript 3.0

Passaggio argomenti in addEventListener + Classe ListenerManager AS3

This is a discussion on Passaggio argomenti in addEventListener + Classe ListenerManager AS3 within the Utilità degli utenti di FlepStudio forums, part of the Flash Italiano category; SCORRI IN FONDO PER LA NUOVA CLASSE ListenerManager! Ciao a tutti ragazzi, stanotte mentre lavoravo ho trovato finalmente quello che ...


Go Back   Forum Flash CS3 Flash CS4 > Flash CS3 Flash CS4 > Flash Italiano > Utilità degli utenti di FlepStudio

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  1 links from elsewhere to this Post. Click to view. #1 (permalink)  
Old 08-08-08, 04:23
just a flasher
 
Join Date: Mar 2008
Posts: 119
Rep Power: 1
Teejay is on a distinguished road
Passaggio argomenti in addEventListener + Classe ListenerManager AS3

SCORRI IN FONDO PER LA NUOVA CLASSE ListenerManager!



Ciao a tutti ragazzi,

stanotte mentre lavoravo ho trovato finalmente quello che cercavo da circa un anno

è stato dibattuto più volte, se ne parla sul web, molti non sanno come fare...

bene ho la soluzione (non sono mica l'unico ) e voglio condividere ciò che ho scoperto stanotte dopo decine di prove


IL PASSAGGIO DI ARGOMENTI TRAMITE addEventListener() E' ORA POSSIBILE!

Vediamo come fare...

Premetto che i workaround a questo problema sono diversi, ma questo è sicuramente il migliore.


Solitamente per passare argomenti con addEventListener facciamo così:

Code:
addEventListener(e, function() { myFunction(arg1 ... argN); })
purtroppo questa soluzione è poco versatile e può essere usata solo se non abbiamo necessità di rimuovere l'eventListener, cosa spesso fondamentale, pensiamo per esempio a un enterFrame, mica lo facciamo runnare per l'eternità...



Un altro metodo consiste nell'associare la funzione anonima di prima ad una variabile, così:
Code:
var fn:Function;
addEventListener(e, fn = function() { myFunction(arg1 ... argN); })
e poi riferirsi ad essa per effettuare la rimozione dell'eventListener...
anche questo metodo ha i suoi contro:
- prima di tutto richiede altro codice
- secondariamente dobbiamo creare una variabile per ogni eventListener (o per lo meno stare molto attenti a non overwritare un riferimento ancora necessario)
- la situazione si complica ulteriormente se abbiamo un numero di eventListener variabile, come ad esempio se essi si trovano in cicli for, while ecc
- talvolta la gestione della cosa è non diventa solo complicata, ma proprio impossibile



E ora ecco la soluzione!

Code:
addEventListener(e, function() { myFunction(arguments.callee, arg1 ... argN); })

function myFunction(referenceToCallerFn:Function, arg1 ... argN) {

       // statements...

       removeEventListener(Event.ENTER_FRAME, referenceToCallerFn);

}
sapevo che gli ingegneri di Adobe non potevano essere così stupidi...

ma devo dire che ce l'hanno messa tutta per complicare le cose (anche se, a fronte, è doveroso ricordarlo, di una velocità di esecuzione 10x, rispetto ad AS2)

hanno tolto anche arguments.caller e la tecnica per ottenere la funzione chiamante è passarla negli argomenti della funzione chiamata


SALUTI A TUTTI, SPERO DI ESSERVI STATO UTILE!!

__________________
_
_

Teejay, just a flasher!
Se vi sono d'aiuto, premete la bilancia!
_

Last edited by Teejay; 29-08-08 at 21:22..
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote

  #2 (permalink)  
Old 15-08-08, 14:44
Junior Member
 
Join Date: Mar 2008
Posts: 17
Rep Power: 0
incvizitor is on a distinguished road
Re: PASSAGGIO PARAMETRI IN addEventListener!!!

Grazie mille!!!!!!!!!!!!!!!!!
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 16-08-08, 14:20
just a flasher
 
Join Date: Mar 2008
Posts: 119
Rep Power: 1
Teejay is on a distinguished road
Riferimento: PASSAGGIO PARAMETRI IN addEventListener!!!

ahahah dov'è finita l'altra parte del messaggio? ---> " Se ero una donna, ti avrei dato un bacio!"
__________________
_
_

Teejay, just a flasher!
Se vi sono d'aiuto, premete la bilancia!
_
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 17-08-08, 10:40
Junior Member
 
Join Date: Mar 2008
Posts: 17
Rep Power: 0
incvizitor is on a distinguished road
Re: Riferimento: PASSAGGIO PARAMETRI IN addEventListener!!!

Quote:
Originally Posted by Teejay View Post
ahahah dov'è finita l'altra parte del messaggio? ---> " Se ero una donna, ti avrei dato un bacio!"
Probabilmente è scomparsa a causa del cambiamento climatico....
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #5 (permalink)  
Old 22-08-08, 02:40
just a flasher
 
Join Date: Mar 2008
Posts: 119
Rep Power: 1
Teejay is on a distinguished road
Riferimento: PASSAGGIO PARAMETRI IN addEventListener!!!

Ciao a tutti,

continuando sull'onda di questo post, vi propongo una Class, fatta da me, sicuramente interessante.

Premetto che non è "allo stato dell'arte" quindi commenti, critiche e consigli sono ben accetti.


__________________________________________________ __________________________________________________


La soluzione che ho proposto precedentemente ha un limite, ovvero i parametri passati vengono valutati al verificarsi dell'evento.
In certe situazione questo può essere un bene, in altre sarebbe meglio che gli argomenti venissero valutati e salvati quando aggiungiamo l'event listener.


NB: si parla solo dei tipi base, tutte le altre classi vengono per forza di cose valutate al verificarsi dell'evento.
Infatti queste ultime vengono passate per puntatore (riferimento in memoria), anzichè copiate come avviene per i tipi base.
I tipi base sono principalmente Array, Boolean, Date, int, Number, String, uint.


__________________________________________________ __________________________________________________


La classe ListenerManager è qui:

Code:
package {
    
    import flash.events.Event;
    import flash.events.EventDispatcher;
    
    public class ListenerManager {
        
        private static var activeListeners:Array = new Array();
        
        public function ListenerManager() {            
            trace("ListenerManager is a static class and should not be instantiated.");
        }
        
        public static function add(object:EventDispatcher, type:String, closure:Function, ...args):void {
            
            var index:Number = exist(object, type, closure);
            
            if (!isNaN(index))
                remove(object, type, closure);
            
            var fn:Function;
            object.addEventListener(type, fn = function(e:Event) { closure(e, args); });
            activeListeners.push(new Listener(object, type, closure, fn));
            
        }
        
        public static function remove(object:EventDispatcher, type:String, closure:Function):Boolean {
            
            var index:Number = exist(object, type, closure);
            
            if (!isNaN(index)) {
                object.removeEventListener(type, activeListeners[index].fn);
                activeListeners[index] = null;
                return true;
            }
            
            return false;
            
        }
        
        private static function exist(object:EventDispatcher, type:String, closure:Function):Number {
            
            for (var i:int = 0; i < activeListeners.length; i++) {
                
                if (activeListeners[i] != null &&
                        object == activeListeners[i].object &&
                            type == activeListeners[i].type &&
                                closure == activeListeners[i].closure)
                    
                    return i;
                
            }
            
            return Number.NaN;
            
        }
        
    }
    
}
__________________________________________________ __________________________________________________


La classe Listener, necessaria per la classe ListenerManager, è invece definita così:

Code:
package {
    
    import flash.events.EventDispatcher;
    
    public class Listener {
        
        public var object:EventDispatcher;
        public var type:String;
        public var closure:Function;
        public var fn:Function;
        
        public function Listener(object:EventDispatcher, type:String, closure:Function, fn:Function) {
            
            this.object = object;
            this.type = type;
            this.closure = closure;
            this.fn = fn;
            
        }
        
    }
    
}
__________________________________________________ __________________________________________________


La classe ListenerManager, statica, possiede 2 metodi pubblici, add e remove:

add( object:EventDispatcher, type:String, closure:Function, ...args ) as void
remove( object:EventDispatcher, type:String, closure:Function ) returns Boolean

Mettiamo che vogliamo associare un event listener enterFame al movieclip pippo, facendo sì che chiami la funzione pippoEnterFrame con gli argomenti a, b, c.

Code:
ListenerManager.add( pippo, "enterFrame", pippoEnterFrame, a, b, c );
La funzione pippoEnterFrame riceve poi gli argomenti come un array, facilmente accessibile:

Code:
function pippoEnterFrame( e:Event, params:Array ) {

       trace( e );                // traces the event object

       trace( params[0] );        // traces the value of a, when setting up the listener   
       trace( params[1] );        // traces the value of b, when setting up the listener   
       trace( params[2] );        // traces the value of c, when setting up the listener   

}
__________________________________________________ __________________________________________________


Per rimuovere l'event listener impostato basterà usare la funzione remove:

Code:
ListenerManager.remove( pippo, "enterFrame", pippoEnterFrame );
Questa funzione ritorna un booleano, true nel caso che tutto sia andato bene, false in caso di errori.

__________________________________________________ __________________________________________________


E' possibile impostare un solo event listener per ogni combinazione [oggetto, tipo, funzione] come del resto accade con il canonico addEventListener.

Se viene fatta una chiamata alla funzione add con la stessa combinazione [oggetto, tipo, funzione] ma con parametri differenti, questi ultimi vengono aggiornati.



In allegato al post, trovate lo zip con la classe e la relativa licenza (Creative Commons BY-ND 3.0).

Spero ancora una volta di essere stato d'aiuto!
Attached Files
File Type: zip ListenerManager_by_Teejay.zip (1.4 KB, 4 views)

__________________
_
_

Teejay, just a flasher!
Se vi sono d'aiuto, premete la bilancia!
_

Last edited by Teejay; 24-08-08 at 23:32..
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #6 (permalink)  
Old 23-08-08, 08:51
Administrator
 
Join Date: Jul 2007
Location: Cesena
Posts: 4,535
Rep Power: 6
Flep is on a distinguished road
Re: PASSAGGIO PARAMETRI IN addEventListener!!!

Grazie Teejay !
Bella classe.
__________________

 


I recommend: Essential Actionscript 3.0

- I do not reply technicians pvt messages. Open a thread !
- Non rispondo ai messaggi privati con domande tecniche. Apri una discussione sul forum !
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #7 (permalink)  
Old 29-08-08, 20:30
just a flasher
 
Join Date: Mar 2008
Posts: 119
Rep Power: 1
Teejay is on a distinguished road
Rilasciata una nuova versione della ListenerManager class!!!

Supporto a:
  • passaggio argomenti in via nativa (non più necessario l'array in ricezione)
  • passaggio opzionale dell'evento che si è scatenato
  • cambio dello scope, cioè del thisObject, per la function anonime


Si importa con:

Code:
import it.maxxmedia.utils.ListenerManager;
Il nuovo metodo add è così descritto:

ListenerManager.
add (
object:EventDispatcher,
type:String,
closure:Function,
args:Array = null,
passEvent:Boolean = false,
scope:Object = null
) as void



dove:
object è l'oggetto a cui si aggiunge l'eventListener
type è il tipo dell'evento
closure è la funzione da chiamare quando si verifica l'evento
args è un array di argomenti da passare alla funzione (opzionale, default = null)
passEvent è un bool che indica se passare anche l'evento (opzionale, default = false)
scope è l'oggetto a cui punta il this per le funzioni anonime (opzionale, default = object)

Vediamo un esempio pratico:

Code:
var myMovie:MovieClip = new MovieClip();

ListenerManager.add ( myMovie, "click", myFunct, ["passed", "string"], true);

function myFunct ( e:Event, arg1:String, arg2:String ) { ...codice... }
Con le funzioni anonime:
Code:
var myMovie:MovieClip = new MovieClip();
var myString:String = "lamiastringa";

ListenerManager.add ( myMovie, "click", function( s:String ) { trace( this ); }, ["stringa"], false, myString );
Il trace darà in output "lamiastringa" in quando il suo this vale myString, come impostato nell'argomento scope della funzione add.

__________________________________________________ __________________________________________________


ATTENZIONE: se dovete passare un solo argomento, esso va comunque passato all'add come array (es. [mioOggetto] ).

__________________________________________________ __________________________________________________


Se non volete passare argomenti ma volete comunque passare l'evento e/o impostare uno scope differente, potete passare come argomento args:
  • [ ]
  • new Array()
  • null
in modo da fornire un elemento nullo o vuoto.


Se non avete necessità di passare l'evento e/o impostare lo scope, potete semplicemente passare la funzione con solo 3 argomenti.



Il metodo remove è rimasto invariato:

remove( object:EventDispatcher, type:String, closure:Function ) returns Boolean

Ritorna true se l'eventListener è stato trovato e rimosso, false altrimenti.



Allego uno zip con source e licenza (Creative Commons BY-ND 3.0).


Per ogni informazione non esitate a postare o contattarmi!


Ciao a tutti!
Attached Files
File Type: zip ListenerManager.zip (2.1 KB, 13 views)

__________________
_
_

Teejay, just a flasher!
Se vi sono d'aiuto, premete la bilancia!
_

Last edited by Teejay; 29-08-08 at 20:38..
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #8 (permalink)  
Old 03-12-08, 15:45
Junior Member
 
Join Date: Dec 2007
Posts: 3
Rep Power: 0
Giginiello is on a distinguished road
Re: Passaggio argomenti in addEventListener + Classe ListenerManager AS3

Ciao Teejay,
innanzitutto conplimenti per la tua classe davvero molto utile.

La stavo testando per la lettura di un file XML ed avrei un quesito da porti.
Ho una funzione così strutturata:

Code:
function myLoadXML(xmlPath:String):void {

var mXMLLoader:URLLoader = new URLLoader();
var mXMLRequest:URLRequest = new URLRequest(xmlPath);
ListenerManager.add(mXMLLoader, IOErrorEvent.IO_ERROR, mXMLError, [xmlPath],  true);
ListenerManager.add(mXMLLoader, Event.COMPLETE, mXMLOK, [xmlPath], true);
mXMLLoader.load(mXMLRequest);
}
Le due funzioni di gestione degli eventi sono così:

Code:
function mXMLError(errorEvent:IOErrorEvent, xmlPath:String):void {
trace("impossibile leggere: " + xmlPath);
}

function mXMLOK(myEvent:Event, xmlPath:String):void {
trace("ok, letto con successo: " + xmlPath);
}
E fin qui nulla di nuovo, ho seguito le tue indicazioni e tutto funziona alla perfezione. Il problema si presenta quando voglio rimuovere i listener di eventi aggiunti all'oggetto mXMLLoader e quindi ho bisogno di far riferimento ad esso all'interno delle funzioni di gestione degli eventi.

Seguendo le tue indicazioni ho provato facendo così:

Code:
function mXMLError(errorEvent:IOErrorEvent, xmlPath:String):void {
trace("impossibile leggere: " + xmlPath);
(*)ListenerManager.remove(errorEvent.target, IOErrorEvent.IO_ERROR, mXMLError);
}
Ma in fase di compilazione ricevo questo errore:
(*): Assegnazione forzata implicita di un valore di tipo statico Object a un tipo flash.events:EventDispatcher che potrebbe non essere correlato.

In pratica non riesco a fare riferimento al dispatcher che ha generato l'evento all'interno della funzione di gestione dell'errore. (l'asterisco indica la riga che ha generato il messaggio di errore).
Al momento ho risolto passando come argomento di input anche l'oggetto (dispatcher) che genera l'evento e poi chiamando su di esso il metodo remove della tua clase ListenerManager, così:

Code:
ListenerManager.add(mXMLLoader, IOErrorEvent.IO_ERROR, mXMLError, [xmlPath, mXMLLoader],  true);

function mXMLError(errorEvent:IOErrorEvent, xmlPath:String, dispatcher:EventDispatcher):void {
trace("impossibile leggere: " + xmlPath);
ListenerManager.remove(dispatcher, IOErrorEvent.IO_ERROR, mXMLError);
}
Però mi sembra una soluzione poco ortodossa, è questo l'unico modo di procedere quando gli oggetti che generano gli eventi sono interni a delle funzioni e quindi non accessibili a livello globale? O c'è qualche cosa che non ho ben capito che mi porta a non vedere soluzioni alternative?

Attendo un tuo cortese feedback, grazie in anticipo per l'aiuto che saprai offrirmi.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #9 (permalink)  
Old 04-12-08, 03:21
just a flasher
 
Join Date: Mar 2008
Posts: 119
Rep Power: 1
Teejay is on a distinguished road
Riferimento: Re: Passaggio argomenti in addEventListener + Classe ListenerManager AS3

E' maledettamente tardi quindi ti rispondo al volo

Il riferimento al target c'è, ma flash lo resituisce come Object mentre la classe accetta in input sulla remove solo tipi EventDispatcher.

Puoi provare a usare currentTarget, anzichè target, ma non dovrebbe cambiare nulla perchè da una veloce letta alla guida ho visto che anche questa proprietà è restituita genericamente come Object.

Puoi tuttavia fare un cast al tipo EventDispatcher così:

Code:
ListenerManager.remove(EventDispatcher(errorEvent.target), IOErrorEvent.IO_ERROR, mXMLError);
Così dovrebbe funzionare.



Andando un po' OT, ho tante cose da migliorare nella classe, ma purtroppo con lo studio non ho nemmeno il tempo di respirare.
__________________
_
_

Teejay, just a flasher!
Se vi sono d'aiuto, premete la bilancia!
_
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #10 (permalink)  
Old 04-12-08, 09:14
Junior Member
 
Join Date: Dec 2007
Posts: 3
Rep Power: 0
Giginiello is on a distinguished road
Re: Riferimento: Re: Passaggio argomenti in addEventListener + Classe ListenerManager

Quote:
Originally Posted by Teejay View Post
E' maledettamente tardi quindi ti rispondo al volo
Puoi tuttavia fare un cast al tipo EventDispatcher così:

Code:
ListenerManager.remove(EventDispatcher(errorEvent.target), IOErrorEvent.IO_ERROR, mXMLError);
Così dovrebbe funzionare.
Si così funge, grazie mille.

Quote:
Originally Posted by Teejay View Post
Andando un po' OT, ho tante cose da migliorare nella classe, ma purtroppo con lo studio non ho nemmeno il tempo di respirare.
Resto sintonizzato, appena rilasci una nuova versione la testo e ti faccio sapere.
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote

Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump