2010-03-19 18 views
5

Je cherche un moyen d'ajouter un EventListener qui s'enlèvera automatiquement après la première fois qu'il se déclenchera, mais je n'arrive pas à trouver une façon de le faire comme je le souhaite .AS3 - Ecouteur d'événement qui ne se déclenche qu'une seule fois

Je trouve cette fonction (here):

public class EventUtil 
{ 
    public static function addOnceEventListener(dispatcher:IEventDispatcher,eventType:String,listener:Function):void 
    { 
     var f:Function = function(e:Event):void 
     { 
       dispatcher.removeEventListener(eventType,f); 
       listener(e); 
      } 
      dispatcher.addEventListener(eventType,f); 
    } 
} 


Mais au lieu d'avoir à écrire:

EventUtil.addOnceEventListener(dispatcher, eventType, listener); 

Je voudrais l'utiliser de la manière habituelle:

dispatcher.addOnceEventListener(eventType, listener); 


Est-ce que quelqu'un a une idée de comment cela pourrait être fait ne?
Toute aide serait grandement appréciée.


(je sais que Robert Penner de Signals peut le faire, mais je ne peux pas les utiliser car cela signifierait beaucoup de réécriture du code que je ne peux pas se permettre pour mon projet en cours)

+0

Essayez d'utiliser le (https://github.com/robertpenner/as3-signals/wiki) [Bibliothèque de signaux]. –

Répondre

11

je trouve la façon la plus propre sans utiliser ou chambouler statics votre code avec le bruit est de définir une fonction globale (dans un fichier appelé removeListenerWhenFired.as) comme ceci:

package your.package 
{ 
    import flash.events.Event; 
    import flash.events.IEventDispatcher; 

    public function removeListenerWhenFired(callback:Function, useCapture:Boolean = false):Function 
    { 
     return function (event:Event):void 
     { 
      var eventDispatcher:IEventDispatcher = IEventDispatcher(event.target) 
      eventDispatcher.removeEventListener(event.type, arguments.callee, useCapture) 
      callback(event) 
     } 
    } 
} 

Ensuite, vous pouvez écouter des événements comme ceci:

import your.package.removeListenerWhenFired 

// ... class definition 

    sprite.addEventListener(MouseEvent.CLICKED, 
     removeListenerWhenFired(
      function (event:MouseEvent):void { 
       ... do something 
      } 
     ) 
    ) 
+0

C'est une belle astuce à laquelle je n'ai pas pensé, merci! –

+0

pas de problème;) les fermetures sont en effet très pratiques. Je construis un sac plein de trucs de fermeture et de fonctions globales, pour voir où tout cela va aller. –

+0

Comment supprimer manuellement un tel écouteur, puisque l'écouteur que vous ajoutez est une fonction anonyme? Si vous ne pouvez pas le supprimer manuellement, tôt ou tard, vous aurez un bug. – chichilatte

2

I Vous ne l'avez pas essayé, mais vous pouvez simplement transformer la méthode statique EventUtil en une méthode standard et étendre la classe dans votre objet.

public class OnceEventDispatcher 
{ 
    public function addOnceEventListener(eventType:String,listener:Function):void 
    { 
     var f:Function = function(e:Event):void 
     { 
       this.removeEventListener(eventType,f); 
       listener(e); 
      } 
      this.addEventListener(eventType,f); 
    } 
} 

public class Example extends OnceEventDispatcher 
{ 


} 

var ex:Example = new Example(); 
ex.addOnceEventListener(type, func); 
+0

Je ne peux pas utiliser l'héritage car AS3 n'autorise pas l'héritage multiple, et la plupart de mes classes en étendent déjà une autre. J'ai pensé mettre cette fonction dans un fichier .as externe que je vais inclure dans toutes mes classes, mais je me demandais s'il y avait une meilleure façon de le faire. –

+0

Je pourrais également ajouter la fonction à la classe UIComponent directement dans le Flex SDK; ça résoudrait mon problème, mais c'est encore plus laid =/ –

1
functionadd.addEventListener(COMPLETE,functionremove); 

functionremove() 
{ 
    runevent(); 
    functionadd.removeEventListener(COMPLETE,functionremove); 
} 
function runevent() 
{ 
    trace('Hello'); 
}