Форум 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=165957)

Genm 28.08.2011 19:03

Автоматическое удаление всех потомков и прослушивателей
 
Всем привет,

Давайте представим такую ситуацию, что Вы создали страничку. На ней много картинок, кнопок с прослушивателями, пользовательский курсор да еще и прицепленный к stage ENTER_FRAME. Вы ее посмотрели и захотели закрыть. Сделав так: page = null, у нас в итоге все прослушиватели остануться висеть в памяти. Тогда что удалять каждый прослушиватель ручками? Нет это не наш путь, нам ведь так лениво!

Вместо кропотливой писанины по удалению прослушивателей давайте лучше будем наследовать все классы где установлены прослушиватели от класса Basic. Тогда используя addEL можно устанавливать прослушиватели и заодно их регистрировать. А для очистки страницы используем метод free(page).

Хотел добавить эту запись в блог, чтобы тема не потерялась, но видно не судьба...

Код AS3:

package {
        import flash.display.*
        import flash.events.*
        import flash.utils.*
 
public class Basic extends Sprite {
        //Массив установленных прослушивателей
        public var myArrayListeners:Array = [];
/**
 * Ставим прослушиватель и метку
 * @param        conteiner
 * @param        type
 * @param        listener
 * @param        useCapture
 * @param        priority
 * @param        useWeakReference
 * @param        onStage
 */

public function addEL(conteiner:Object,type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
        //Добавляем слушатель только, если такого слушателя еще нет
        var instance:Object
        var aLengh:uint = myArrayListeners.length
        for (var i:uint = 0; i < aLengh; i++ ) {
                instance = myArrayListeners[i]
                //Находим элемент из массива
                if (instance.type == type && instance.listener == listener && instance.conteiner == conteiner) {
                        //throw new Error("Такой прослушиватель уже есть");
                        return
                }
        }
        //Добавляем прослушиватель после проверки
        conteiner.addEventListener (type, listener, useCapture, priority, useWeakReference);
        //Добавляем в массив метку
        myArrayListeners.push( { type:type, listener:listener, conteiner:conteiner } );
}
/**
 * Удаляем прослушиватель и убираем метку
 * @param        conteiner
 * @param        type
 * @param        listener
 * @param        useCapture
 * @param        onStage
 */

public function removeEL(conteiner:Object,type:String, listener:Function, useCapture:Boolean = true):void {
        //Находим в массиве флаг слушатель которого удалили
        var instance:Object
        var aLengh:uint = myArrayListeners.length
        for (var i:uint = 0; i < aLengh; i++ ) {
                instance = myArrayListeners[i]
                //Находим и удаляем элемент из массива
                if (instance.type == type && instance.listener == listener && instance.conteiner == conteiner) {
                        conteiner.removeEventListener (type, listener, useCapture);
                        myArrayListeners.splice(i, 1)
                        return
                }
        }
}
/**
 * Очистка контейнеров от данных
 * @param        conteiner
 * @param        clearAll
 */

public function free(conteiner:Object, clearAll:Boolean = false):void {
        if(conteiner!=null){
                //Определяем класс полученного контейнера
                var myClass:Class = getDefinitionByName(getQualifiedClassName(conteiner)) as Class;
                //Обрабатываем объект
                var cLength:uint = 0
                if (myClass == Array) {
                        //Размер массива
                        cLength = conteiner.length
                        //Очищаем массив от объектов
                        while (--cLength > -1) {
                                //Ощищаем и объекты входящие в данный объект
                                free(conteiner[cLength])
                                //Удаляем компоненты
                                conteiner.splice(cLength, 1);
                        }
                }
                cLength = 0
                if (myClass == Object) {
                        //Очищаем контейнер от объектов
                        for (var item1:String in conteiner) {
                                //Ощищаем и объекты входящие в данный объект
                                free(conteiner[item1])
                                //Удаляем объект
                                delete conteiner[item1]
                        }
                }
                //Создаем локальную переменную
                var localArrayListeners:Array
                //Проверяем массив прослушивателей
                var checkListeners:Boolean = conteiner.hasOwnProperty("myArrayListeners")
                //Если есть, то работаем с ней
                if (checkListeners) {
                        localArrayListeners = conteiner.myArrayListeners
                }else {
                        localArrayListeners = myArrayListeners
                }
                //Проверяем есть ли потомки
                var checkСhildrens:Boolean = conteiner.hasOwnProperty("numChildren")
                //Обрабатываем спрайты
                if (checkСhildrens) {
                        //Очищаем контейнер от прослушивателей
                        var instance:Object
                        //Создаем локальные переменные
                        var localConteiner:Object
                        //Проходим по всем сохраненным прослушивателям
                        for (var j:uint = 0; j < localArrayListeners.length; j++ ) {
                                //Передаем объект по ссылке
                                instance = localArrayListeners[j]
                                localConteiner = conteiner
                                //Проверяем имена дочерних элементов и удаляем у них прослушиватели
                                if (localConteiner.hasEventListener(instance.type) == true) {
                                        //Проверяем класс, чтобы не перебирать лишние элементы
                                        if (instance.conteiner == localConteiner) {
                                                //Удаляем прослушиватель
                                                localConteiner.removeEventListener(instance.type, instance.listener,false)
                                                localConteiner.removeEventListener(instance.type, instance.listener, true)
                                                //Если прослушиватель удален, то удаляем метку из массива прослушивателей
                                                if (localConteiner.hasEventListener(instance.type) == false) {
                                                        localArrayListeners.splice(j, 1)
                                                        //Так как размер массива изменился и данные сместились,то смещаем и счетчик
                                                        j--
                                                }
                                        }
                                }
                        }
                        //Очищаем контейнер от объектов
                        //Колличество дочерних элементов
                        if (conteiner.numChildren != null) {
                                cLength = conteiner.numChildren
                                if (cLength != 0) {
                                        for (var i:uint = 0; i < cLength; i++) {
                                                //Ощищаем и объекты входящие в данный объект
                                                free(conteiner.getChildAt(0))
                                                //Удаляем объект
                                                conteiner.removeChildAt(0)
 
                                        }
                                }
                        }
                        //Удаляем сам контейнер
                        if(clearAll == true){
                                conteiner.parent.removeChild(conteiner)       
                                conteiner = null
                        }
                }else {
                        //Очищаем картинку от данных
                        var checkData:Boolean = conteiner.hasOwnProperty("bitmapData")
                        //Если есть, то работаем с ней
                        if (checkData) {
                                conteiner.bitmapData.dispose()
                        }
                }
        }
}
 
}}


goodguy 28.08.2011 20:38

Для этого просто пишутся методы деструкторы, зануляющие все ненужное и удаляющие все слушатели.
Цитата:

Сделав так: page = null
Кто ж так делает-то )

alatar 28.08.2011 20:52

Ужас.

1. Подписываться на ENTER_FRAME у stage в наследнике DisplayObject бессмысленно. ENTER_FRAME в него и так приходит.
2. Достаточно было переписать addEventListener / removeEventListener и не городить addEL / removeEL
3. Для useCapture создается отдельный слушатель, в вашем же случае удастся подписаться или с useCapture или без, но не вместе.
4. Класс объекта можно получить через:
Код AS3:

var contClass:Class = (container as Object).constructor;

5. Если в ваш Basic положить Bitmap, то он убьет и BitmapData, который может быть использован и в других битмапах. В дополнение, получите RTE, при очистке контейнера, если две битмапы с одной BitmapData будут в него помещены (или в разные контейнеры).
6. Словите RTE, если в Basic будет добавлен наследник DisplayObject, которому добавили свойство bitmapData или наследник Shape, которому добавили свойство numChildren.
Цитата:

Вместо кропотливой писанины по удалению прослушивателей давайте лучше будем наследовать все классы где установлены прослушиватели от класса Basic.
И добавим другую кропотливую писанину. И какой смысл наследоваться от этого класса?

Silicium 28.08.2011 21:16

Меня вот всегда интересовал вопрос: почему массив _listeners в EventDispatcher-е приватный, и разработчики не сделали к нему доступ, хотя бы через геттер. Не понимаю, чем это могло быть плохо?

mayakwd 28.08.2011 21:58

ListenerManager

Genm 28.08.2011 22:08

Goodguy
Чтобы удалить прослушиватели, надо отловить момент удаления объектов прослушивателей. А так все под рукой и можно даже не писать деструкторы.

Alatar
2. Да я не хочу переписывать их, так как они по-моему будут быстрее работать, если надо просто ручками удалять.
3. Не понимаю этот useCapture, всегда использую false и поэтому так все реализовал
4.Спс
5. Согласен использование Basic, налагает ряд ограничений, так как не все моменты охвачены.
-Не знал, что один BitmapData можно сразу нескольким картинкам назначить. Обычно каждой делаю свою. Можно убрать этот dispose, после removeChild сборщик все равно уберет.
-Класс могут наследовать только обьекты с numChildren. Bitmap хоть и имеет addEventListener, но у него не будут удаляться прослушиватели. Хотя это вроде можно реализовать. Но по мне так можно просто не вешать на такие объекты события.

Mayakwd
СПС большое!
-

goodguy 28.08.2011 22:26

Цитата:

Чтобы удалить прослушиватели, надо отловить момент их удаления.
мм.. это как?

Genm 28.08.2011 23:05

goodguy
их - это объекты прослушивателей. Спс изменил...

mayakwd
Цитата:

Сообщение от mayakwd (Сообщение 1026277)

Интересная реализация, сразу много решений захотелось попробывать у себя. Но что хочу отметить, для автоматического удаления прослушивателей у дочерних объектов, все равно надо создавать деструктор. Сами они не удаляться, после удаления объекта.

mayakwd 28.08.2011 23:38

Цитата:

Сообщение от Genm (Сообщение 1026304)
mayakwd

Интересная реализация, сразу много решений захотелось попробывать у себя. Но что хочу отметить, для автоматического удаления прослушивателей у дочерних объектов, все равно надо создавать деструктор. Сами они не удаляться, после удаления объекта.

Ну магии не место в программировании, поэтому, да, деструкторы необходимо писать :-)

gloomyBrain 29.08.2011 01:16

Цитата:

Интересная реализация, сразу много решений захотелось попробывать у себя
Ничего в ней интересного. Как по мне - так можно было бы и лучше. Тем более что со слабыми ссылками она не работает (вернее, работает, но как с сильными)


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

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