Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 28.08.2011, 19:03
Genm вне форума Посмотреть профиль Отправить личное сообщение для Genm Найти все сообщения от Genm
  № 1  
Ответить с цитированием
Genm

Регистрация: Aug 2011
Сообщений: 24
Записей в блоге: 1
Cool Автоматическое удаление всех потомков и прослушивателей

Всем привет,

Давайте представим такую ситуацию, что Вы создали страничку. На ней много картинок, кнопок с прослушивателями, пользовательский курсор да еще и прицепленный к 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()
			}
		}
	}
}
 
}}

Старый 28.08.2011, 20:38
goodguy вне форума Посмотреть профиль Найти все сообщения от goodguy
  № 2  
Ответить с цитированием
goodguy
Banned
[+1 05.11.11]
[+1 09.08.11]

Регистрация: Jan 2010
Адрес: РФ. Кемеровская область
Сообщений: 3,243
Для этого просто пишутся методы деструкторы, зануляющие все ненужное и удаляющие все слушатели.
Цитата:
Сделав так: page = null
Кто ж так делает-то )

Старый 28.08.2011, 20:52
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 3  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Ужас.

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.
И добавим другую кропотливую писанину. И какой смысл наследоваться от этого класса?
__________________
משיח לא בא
משיח גם לא מטלפן

Старый 28.08.2011, 21:16
Silicium вне форума Посмотреть профиль Отправить личное сообщение для Silicium Найти все сообщения от Silicium
  № 4  
Ответить с цитированием
Silicium
 
Аватар для Silicium

Регистрация: Sep 2010
Адрес: Ростов-на-Дону
Сообщений: 369
Меня вот всегда интересовал вопрос: почему массив _listeners в EventDispatcher-е приватный, и разработчики не сделали к нему доступ, хотя бы через геттер. Не понимаю, чем это могло быть плохо?

Старый 28.08.2011, 21:58
mayakwd вне форума Посмотреть профиль Отправить личное сообщение для mayakwd Посетить домашнюю страницу mayakwd Найти все сообщения от mayakwd
  № 5  
Ответить с цитированием
mayakwd

Регистрация: Jul 2008
Адрес: t:2, x: 0.76
Сообщений: 553
Отправить сообщение для mayakwd с помощью ICQ Отправить сообщение для mayakwd с помощью Skype™
ListenerManager

Старый 28.08.2011, 22:08
Genm вне форума Посмотреть профиль Отправить личное сообщение для Genm Найти все сообщения от Genm
  № 6  
Ответить с цитированием
Genm

Регистрация: Aug 2011
Сообщений: 24
Записей в блоге: 1
Goodguy
Чтобы удалить прослушиватели, надо отловить момент удаления объектов прослушивателей. А так все под рукой и можно даже не писать деструкторы.

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

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


Последний раз редактировалось Genm; 28.08.2011 в 22:59.
Старый 28.08.2011, 22:26
goodguy вне форума Посмотреть профиль Найти все сообщения от goodguy
  № 7  
Ответить с цитированием
goodguy
Banned
[+1 05.11.11]
[+1 09.08.11]

Регистрация: Jan 2010
Адрес: РФ. Кемеровская область
Сообщений: 3,243
Цитата:
Чтобы удалить прослушиватели, надо отловить момент их удаления.
мм.. это как?

Старый 28.08.2011, 23:05
Genm вне форума Посмотреть профиль Отправить личное сообщение для Genm Найти все сообщения от Genm
  № 8  
Ответить с цитированием
Genm

Регистрация: Aug 2011
Сообщений: 24
Записей в блоге: 1
goodguy
их - это объекты прослушивателей. Спс изменил...

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

Старый 28.08.2011, 23:38
mayakwd вне форума Посмотреть профиль Отправить личное сообщение для mayakwd Посетить домашнюю страницу mayakwd Найти все сообщения от mayakwd
  № 9  
Ответить с цитированием
mayakwd

Регистрация: Jul 2008
Адрес: t:2, x: 0.76
Сообщений: 553
Отправить сообщение для mayakwd с помощью ICQ Отправить сообщение для mayakwd с помощью Skype™
Цитата:
Сообщение от Genm Посмотреть сообщение
mayakwd

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

Старый 29.08.2011, 01:16
gloomyBrain вне форума Посмотреть профиль Отправить личное сообщение для gloomyBrain Найти все сообщения от gloomyBrain
  № 10  
Ответить с цитированием
gloomyBrain
 
Аватар для gloomyBrain

блогер
Регистрация: Mar 2008
Адрес: РФ, Санкт-Петербург
Сообщений: 2,272
Записей в блоге: 5
Отправить сообщение для gloomyBrain с помощью ICQ Отправить сообщение для gloomyBrain с помощью Skype™
Цитата:
Интересная реализация, сразу много решений захотелось попробывать у себя
Ничего в ней интересного. Как по мне - так можно было бы и лучше. Тем более что со слабыми ссылками она не работает (вернее, работает, но как с сильными)
__________________
...вселенская грусть

Создать новую тему Ответ Часовой пояс GMT +4, время: 17:33.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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