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

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

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

Регистрация: Nov 2009
Сообщений: 5
Post Автоматическое удаление listener-ов при удалении объекта

Доброго времени суток.
Написал простенький класс для вывода мсдж-бокса на экран.


Код AS3:
public class MsgBox extends Sprite {
 
	private const MAX_MSGS_IN_QUEUE:uint = 10;
	public static const TYPE_OK    = 1;
	public static const TYPE_YESNO = 2;
 
	public static const OK	= 1;
	public static const YES	= 2;
	public static const NO	= 3;
 
	private var m_arrMsgs:Vector.<msg_info>;
	private var m_arrBtns:Array;
	private var m_sprBtns:Sprite;
 
 
 
 
	public function MsgBox() {
 
		m_arrMsgs = new Vector.<msg_info>();
		m_sprBtns = new Sprite();
		addChild( m_sprBtns );
		m_sprBtns.addEventListener( MouseEvent.CLICK, OnBtnClick );
		m_arrBtns = new Array();
		visible = false;
 
	} // Конструктор
 
 
 
	public function Create( msg:msg_info ):Boolean {
 
		if( m_arrMsgs.length >= MAX_MSGS_IN_QUEUE )
			return false;
 
		m_arrMsgs.push( msg );
		if( !visible ) Show();
		return true;
 
	} // Create
 
 
 
	private function Show():void {
 
		TfTitle.text = m_arrMsgs[0].title;
		TfText.text  = m_arrMsgs[0].text;
 
		switch( m_arrMsgs[0].type ) {
 
			case TYPE_OK: {
				m_arrBtns[OK]  = CreateButton( "Ok",  xx, yy );
			} break;
 
			case TYPE_YESNO: {
				m_arrBtns[YES] = CreateButton( "Да",  xx, yy );
				m_arrBtns[ NO] = CreateButton( "Нет", xx, yy );
			} break;
 
		} // switch
 
 
		if( !visible ) {
			dispatchEvent( new MsgBoxEvent( MsgBoxEvent.SHOW ) );
			visible = true;
		}
 
	} // Show
 
 
 
	public function Hide():Boolean {
 
		RemoveAllButtons();
		m_arrMsgs.shift();
 
		if( m_arrMsgs.length == 0 ) {
 
			dispatchEvent( new MsgBoxEvent( MsgBoxEvent.HIDE ) );
			visible = false;
			return true;
 
		} else {
 
			Show();
			return false;
		}
 
	} // Hide
 
 
 
	public function OnBtnClick( e:MouseEvent ) {
 
		Hide();
 
	} // OnBtnClick
 
 
 
	private function CreateButton( sCaption:String, x_pos:Number, y_pos:Number ):Button {
 
		var btn:Button = new Button();
		btn.x = x_pos;
		btn.y = y_pos;
		btn.label = sCaption;
		m_sprBtns.addChild( btn );
		return btn;
 
	} // CreateButton
 
 
 
	private function RemoveAllButtons() {
 
		for( var key in m_arrBtns ) {
			m_sprBtns.removeChild( m_arrBtns[key] );
			m_arrBtns[key] = null;
		}
		m_arrBtns = null;
		m_arrBtns = new Array();
 
	} // RemoveAllButtons
 
 
 
	public function GetButton ( id:uint )	{ return m_arrBtns[id]; }
	public function GetButtons() 		{ return m_arrBtns;     }
Предполагалось использовать всю эту конструкцию следующим образом:
Код AS3:
m_MsgBox = new MsgBox();
addChild( m_MsgBox );
 
// Создаем мсдж-бокс
var Msg:msg_info = new msg_info();
Msg.type  = MsgBox.TYPE_YESNO;
Msg.title = 'Вы действительно хотите выйти?';
Msg.text  = 'Выход';
m_MsgBox.Create( Msg );
 
// WeakReference слушатели не помешают кнопке удалиться
m_MsgBox.GetButton( MsgBox.YES ).addEventListener( MouseEvent.CLICK, OnExit  , false, 0, true ); 
m_MsgBox.GetButton( MsgBox.NO  ).addEventListener( MouseEvent.CLICK, Continue, false, 0, true );
Т.е. после того, как создается мсдж-бокс, я просто вешаю на его кнопки слушателей.
И вроде бы всё нормально, но слушателей никто не удаляет. Они так и остаются висеть и ловить сообщения несуществующей кнопки, после того, как мсдж-бокс закрыли. К тому же, приходится использовать WeakReference, чтобы кнопки могли удалиться из памяти.

Прошу совета, как это дело лучше перепроектировать. Переопределить addEventListener для Button? Или вообще запретить получение указателей на кнопки MsgBox-а( тогда при создании мсдж-бокса, нужно будет передать указатель на метод, который дернется при mouseEvent.CLICK )? Или дописывать каждый раз удаление слушателя в вызываемый им же метод? А может есть какой-то секрет удаления слушателей при удалении объекта?

Буду рад услышать любые мнения.

Старый 14.11.2009, 19:11
random13 вне форума Посмотреть профиль Отправить личное сообщение для random13 Найти все сообщения от random13
  № 2  
Ответить с цитированием
random13
 
Аватар для random13

Регистрация: Oct 2006
Адрес: Москва
Сообщений: 889
ну а что вам мешает сделать что то вроде деструктора, который бы вы запускали перед удалением объектов, а в нем удаляли бы ваши слушатели
__________________
Коллекционирую чужие ActionScript Блоги

Старый 14.11.2009, 19:41
Psycho Tiger вне форума Посмотреть профиль Отправить личное сообщение для Psycho Tiger Найти все сообщения от Psycho Tiger
  № 3  
Ответить с цитированием
Psycho Tiger
 
Аватар для Psycho Tiger

блогер
Регистрация: Jun 2005
Адрес: Toronto
Сообщений: 6,601
Записей в блоге: 17
REMOVED_FROM_STAGE, думаю.

Старый 14.11.2009, 19:44
Bomberovich вне форума Посмотреть профиль Отправить личное сообщение для Bomberovich Найти все сообщения от Bomberovich
  № 4  
Ответить с цитированием
Bomberovich

Регистрация: Nov 2009
Сообщений: 5
Цитата:
Сообщение от random13 Посмотреть сообщение
ну а что вам мешает сделать что то вроде деструктора, который бы вы запускали перед удалением объектов, а в нем удаляли бы ваши слушатели
Деструктор кнопки? А откуда кнопка узнает, какие на ней слушатели висят?

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

Регистрация: Feb 2008
Адрес: Череповец
Сообщений: 623
Отправить сообщение для Felicast с помощью ICQ
зачем вам давать доступ кому попало к своим кнопкам. никакого GetButton быть не должно.
надо отсылать события самим классом MsgBox. например, OK_CLICKED, CANCEL_CLICKED.
и подписываться к MsgBox, а не к его кнопкам
__________________
я могу стать всем, если только захочу

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

Регистрация: Nov 2009
Сообщений: 5
Цитата:
Сообщение от Felicast Посмотреть сообщение
зачем вам давать доступ кому попало к своим кнопкам. никакого GetButton быть не должно.
надо отсылать события самим классом MsgBox. например, OK_CLICKED, CANCEL_CLICKED.
и подписываться к MsgBox, а не к его кнопкам
А ничего, что придется переписать все нужные события( PRESS, CLICK, ... ) для всех возможных кнопок? Может быть сделать одно событие MsgBox-а BTN_PRESS, BTN_CLICK,... с полем BtnID, а не для каждой кнопки? Или это те же яйца?

Старый 15.11.2009, 00:19
Felicast вне форума Посмотреть профиль Отправить личное сообщение для Felicast Найти все сообщения от Felicast
  № 7  
Ответить с цитированием
Felicast
 
Аватар для Felicast

Регистрация: Feb 2008
Адрес: Череповец
Сообщений: 623
Отправить сообщение для Felicast с помощью ICQ
Цитата:
А ничего, что придется переписать все нужные события( PRESS, CLICK, ... ) для всех возможных кнопок?
да собственно ничего (вы не заглядывали, сколько флексовые компоненты генерируют событий? и это вполне нормально)
Цитата:
Может быть сделать одно событие MsgBox-а BTN_PRESS, BTN_CLICK,... с полем BtnID, а не для каждой кнопки?
можно. только BtnID - строковое обозначение кнопки (типа MsgBox.YES, MsgBox.OK ...)
__________________
я могу стать всем, если только захочу

Старый 15.11.2009, 00:25
GentleFLASH вне форума Посмотреть профиль Отправить личное сообщение для GentleFLASH Найти все сообщения от GentleFLASH
  № 8  
Ответить с цитированием
GentleFLASH

Регистрация: Apr 2009
Сообщений: 117
Bomberovich, а что мешает MsgBox генерировать событие DESTROY или CLOSE и вам подписываться на это событие, где уже ручками можно было бы снять все листенеры?
Ну или хотя бы коллбак организовать, типа onClose

Старый 15.11.2009, 11:59
Bomberovich вне форума Посмотреть профиль Отправить личное сообщение для Bomberovich Найти все сообщения от Bomberovich
  № 9  
Ответить с цитированием
Bomberovich

Регистрация: Nov 2009
Сообщений: 5
Felicast
GentleFLASH

Хотелось бы избежать удаления слушателей кнопок(или самого MsgBox-a) внешним классом. Удаляется кнопка - должны удалится все ее слушатели.

Пока в голову приходит только:
Код AS3:
class MsgBox {
 
   // Только с помощью этого метода можно будет повесить любого слушателя на любую кнопку
   public function addEventListenerToButton( uiBtnID:uint, type:String, listener:Function ) {
      m_listeners.push( { uiBtnID:uiBtnID, type:type, listener:listener } );
      m_arrBtns[uiBtnID].addEventListener( type, listener, false, 0, true );
   } // addEventListenerToButton
 
   // Вызывается при удалении кнопок
   private function RemoveAllButtonListeners() {
      for( var i:uint=0; i<m_listeners.length; i++ )
         m_arrBtns[m_listeners[i].uiBtnID].removeEventListener( m_listeners[i].type, m_listeners[i].listener, false, 0, true );
         m_listeners = new Array();
   } // RemoveAllButtonListeners
 
}

Старый 15.11.2009, 12:29
etc вне форума Посмотреть профиль Найти все сообщения от etc
  № 10  
Ответить с цитированием
etc
Et cetera
 
Аватар для etc

Регистрация: Sep 2002
Сообщений: 30,787
Можно переопределить addEventListener у самого MsgBox. И вообще, подписываться только у него на кастомные события типа RESULT_YES, RESULT_NO и т. п.. Когда происходит REMOVED_FROM_STAGE, удалять подписчиков.

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

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

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


 


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


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