Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Как управлять слушателями? (http://www.flasher.ru/forum/showthread.php?t=131256)

bjd 16.10.2009 01:28

Как управлять слушателями?
 
Подскажите, пожалуйста, наиболее простой и эффективный способ удаления обработчиков событий, созданных в экземплярах классов? Возможно, ли передавать ссылки на созданные слушатели в специально предназначенный для этого класс и при необходимости пройтись по ссылкам и удалить все слушатели? Если да, подскажите, как это реализовать? А если нет, то подскажите альтернативу...

FX2000 16.10.2009 01:53

Удалить, например, addEventListener(Event.ENTER_FRAME, doSmth); можно с помощью
removeEventListener(Event.ENTER_FRAME, doSmth);

Lecosson 16.10.2009 02:14

Я сделал иначе - во всех проектах использую свой Sprite, унаследованный от обычного спрайта, но с переопределенными методами (например, addEventListener).
Мой вариант имеет свой небольшой пул, куда складывает все имеющиеся в нем листенеры, слушает удаление себя, при этом убивает всех своих слушателей, детей и благополучно дохнет сам.
По возможности - слежу за удалением сам, но если где-то накосячу - мой класс сам себя подчистит. Кстати, помогает в отладке - при удалении спрайта со сцены сразу можно оттрейсить, где какой слушатель остался висеть.

bjd 16.10.2009 02:19

Lecosson

Если не жалко, поделись примером или исходником...

switcher! 17.10.2009 17:37

bjd, лови.
Например, вот так:
Код AS3:

package
{
        import flash.display.Sprite;
        import flash.events.Event;
 
        public class Example extends Sprite
        {
                //массив со списком слушателей
                private var arr:Array = new Array();
 
                function Example():void
                {
                        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
                }
 
                // переписываем оригинальную функцию
                public override function addEventListener(type:String, listener:Function,
                useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
                {
                        super.addEventListener(type, listener, useCapture, priority, useWeakReference); //вызываем оригинальную (не override) функцию
                        arr.push([type, listener]); //обновляем массив arr новым слушателем
                }
 
                public override function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
                {
                        super.removeEventListener(type, listener, useCapture); //вызываем оригинальную (не override) функцию
 
                        var arr:Array = this.arr; //создаем локальную ссылку на массив, чтобы ускорить код в этой функции
                        var len:int = arr.length;
 
                        // проходимся по массиву от конца к началу, дабы удаление элементов не повлияло на актуальность операций
                        for (var i:int = len-1; i >= 0; i--)
                        {
                                if (type === arr[i][0]) //если удаляемый тип слушателя найден...
                                {
                                        arr.splice(i, 1); // удаляем весь элемент-массив (т.е. тип_слушателя_+_ссылка_на_функцию)
                                }
                        }
                }
 
                private function addedToStage(e:Event):void
                {
                        addEventListener(Event.REMOVED_FROM_STAGE, removeListeners);
                        removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
                }
 
                private function removeListeners(e:Event):void
                {
                        removeEventListener(Event.REMOVED_FROM_STAGE, removeListeners);
 
                        var arr:Array = this.arr; //создаем локальную ссылку на массив, чтобы ускорить код в этой функции
                        var len:int = arr.length;
 
                        //Проходимся по всему списку массива сло слушателя и ВСЕХ их удаляем.
                        for (var i:int = len-1; i >= 0; i--)
                        {
                                removeEventListener(arr[i][0], arr[i][1]);
                        }
 
                        addEventListener(Event.ADDED_TO_STAGE, addedToStage);
 
                        while (this.numChildren > 0) // если у объекта есть дети, удаляем их
                        {
                                removeChildAt(0);
                        }
                }
    }
}


Lecosson 18.10.2009 00:55

У меня почти то же самое:

Код AS3:

package MyPackage
{
import flash.display.Sprite;
import flash.events.Event;
 
public class MySprite extends Sprite
{
private var listenerPool:Array; // в этом массиве хранятся все события, на которые подписывается данный спрайт
 
public function MySprite()
{
listenerPool=new Array();
super();
// добавляем слушатель на удаление спрайта - уничтожить при этом слушателей
super.addEventListener(Event.REMOVED, removeAllEvents);
 
}
 
private function removeAllEvents(event:Event):void
{
if (event.target == this) //только если это событие удаления именно этого спрайта
{ super.removeEventListener(Event.REMOVED, removeAllEvents);
while(listenerPool.length > 0)
{
var pool:Array=listenerPool.pop();
removeEventListener(pool[0], pool[1], pool[2]);
}
}
}
 
public override function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void
{ super.addEventListener(type, listener, useCapture, priority, useWeakReference);
var pool:Array=new Array();
pool[0]=type;
pool[1]=listener;
pool[2]=useCapture;
listenerPool.push(pool);
}
 
 
public override function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void
{ // эта функция удаляет слушатель спрайта и убирает его из массива слушателей
super.removeEventListener(type, listener, useCapture);
function removeListener(a:Object, index:int, source:Array):Boolean
{
if ((a[0] == source[index][0]) && (a[1] == source[index][1]) && (a[2] == source[index][2]))
return (true);
return (false);
}
listenerPool.filter(removeListener);
}
}


bjd 18.10.2009 01:50

Всем спасибо!

etc 18.10.2009 12:33

И никто из ответивших не проверяет, есть ли такой слушатель в массиве при добавлении или нет.

switcher! 18.10.2009 15:25

по хорошему - надо бы ))
Это будет на совести программиста , чтобы не добавлял слушатель, когда он уже добавлен. Хз... я такие вещи четко держу в голове.
Однако, в команде, если не уверен в партнерах, или, наоборот, если хочешь снять с них заботу по слежению за слушателями - может пригодиться. Но и в этом случае по факту вторичного добавления слушателя - нужно генерить ошибку, чтобы потом эти непредусмотренные добавления не вышли боком.
Как-то так -)

etc 18.10.2009 18:43

По хорошему будет не писать больше подобных классов.


Часовой пояс GMT +4, время: 01:01.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.