Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   совместное использование Delegate и EventDispatcher (http://www.flasher.ru/forum/showthread.php?t=89659)

Ромастый 20.12.2006 18:02

совместное использование Delegate и EventDispatcher
 
Все знают, что Delegate.create каждый раз возвращает новый объект. И подписавшись раз на событие таким макаром
Код:

myObject.addEventListener("myEvent", Delegate.create(myOtherObject, myOtherObjectMethod));
Отписаться от него потом весьма проблематично.

Можно отписаться от него в самом методе в момент вызова через arguments.caller (с) NoxNoctis

А если надо извне, в любой другой момент?
Вот, тут подумалось, что можно просто обойти цепочку:
Код:

class DelegateRemover {
        public static function removeDelegate(dispatcher, event, obj, func) {
                var queue = dispatcher["__q_"+event];
                var l:Number = queue.length;
                var i:Number;
                for (i=0; i<l; i++) {
                        var o = queue[i];
                        if (typeof(o) == "function" && o.target == obj && o.func == func) {
                                queue.splice(i, 1);
                                return;
                        }
                }
        }
}

Скажем есть класс
Код:

import mx.utils.Delegate;
//
class MyClass {
        var id;
        function MyClass(ID) {
                id = ID;
        }
        function addEvent(event, obj) {
                obj.addEventListener(event, Delegate.create(this, report));
        }
        function report(obj) {
                trace(id+"  "+obj.type);
        }
}

В первом кадре пишем:
Код:

import mx.events.EventDispatcher;

var mo = new Object();
EventDispatcher.initialize(mo);  // Создали вещатель

myC1 = new MyClass("myC1"); 
myC1.addEvent("onEvent", mo);  // Создали экземпляр myClass и подписали его на onEvent

myC2 = new MyClass("myC2");
myC2.addEvent("onEvent", mo); // Создали контрольный экземпляр

mo.dispatchEvent({type:"onEvent"});  //  trace  myC2  onEvent  myC1  onEvent
trace("_____________________________________________");
DelegateRemover.removeDelegate(mo, "onEvent", myC1, myC1.report); // удалили
mo.dispatchEvent({type:"onEvent"});  // trace myC2  onEvent


etc 20.12.2006 18:29

Что-то мне подсказывает, что при таком подходе ты можешь удалить не тот обработчик…

Ромастый 20.12.2006 18:32

Цитата:

Сообщение от __etc
Что-то мне подсказывает, что при таком подходе ты можешь удалить не тот обработчик…

Есть такой момент... но только в том случае, если создано более одного делегата.
А смысл вешать два и более делегатов на одно событие?

etc 20.12.2006 18:37

Ну случаев, когда обработчиков больше одного может быть много.
Три варианта:
1) Написать свой EventDispatcher (или найти более правильный, который работает по типу EventDispatcher в AS3, там не требуется делегата)

2) Написать отдельный класс, который будет хранить ссылку на делегированную функцию и по вызову убивать подписку.

3) Хранить ссылку внутри класса (нерационально)

Ромастый 20.12.2006 18:45

Цитата:

Сообщение от __etc
Ну случаев, когда обработчиков больше одного может быть много.

Хм... поясни. Несколько раз подписать одну и ту же функцию на одно событие? Зачем?
Во всех прочих случаях удаляется нужный обработчик.

Цитата:

Сообщение от __etc
3) Хранить ссылку внутри класса (нерационально)

Ага, замучался :))

Ромастый 20.12.2006 20:15

В порядке теста навешал до двух десятков различных - все работает, удаляется только нужный.
ПРоблемы возникают только при многократном:
Код:

myObject.addEventListener("onEvent", Delegate.create(MyOtherObject, method));
myObject.addEventListener("onEvent", Delegate.create(MyOtherObject, method));

... и т.д.
Лечится исключительно опять же многократным вызовом:
Код:

DelegateRemover.removeDelegate(myObject, "onEvent", MyOtherObject, method);
DelegateRemover.removeDelegate(myObject, "onEvent", MyOtherObject, method);
...

Но повторюсь - не вижу смысла несколько раз вешать один и тот же обработчик на одно и тоже событие...

Так же вроде все нормально работает с макромедийными компонентами :away:

Ромастый 07.02.2007 16:59

Гыгы.
Удаляются все подписчики-клоны, созданные Delegate'ом, ежели цикл for заменить на for in и убрать нафих выход из метода. :rolleyes:

Код:

class DelegateRemover {
        public static function removeDelegate(dispatcher, event, obj, func) {
                var queue = dispatcher["__q_"+event];
                for (var i in queue) {
                        var o = queue[i];
                        if (typeof(o) == "function" && o.target == obj && o.func == func) {
                                queue.splice(i, 1);
                               
                        }
                }
        }
}


Ромастый 07.02.2007 17:00

Стормозил :rolleyes:

etc 07.02.2007 17:17

Кстати, Нокс предлагал решение удаления типа arguments.caller.removeEventListener ('someEvent',arguments.callee)

Nirth 07.02.2007 17:43

А чем не подходит вариант которым польюзуются тысячи программистов на C#

Код:


var onSomeEventDelegate:Function = Delegate.create(...);

myInstance.addEventDispatcher("someEvent", onSomeEventDelegate);
myInstance.removeEventDispatcher("someEvent", onSomeEventDelegate);



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

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