Показать сообщение отдельно
Старый 23.08.2011, 17:22
botbot вне форума Посмотреть профиль Отправить личное сообщение для botbot Найти все сообщения от botbot
  № 13  
Ответить с цитированием
botbot

Регистрация: Feb 2011
Сообщений: 100
-De-, спасибо за вариант. На больших наборах данных он будет оптимальным. В данном случае списки у меня небольшие, но если вдруг будут большие - именно такое решение буду пользовать.

Цитата:
Сообщение от GBee Посмотреть сообщение
Может задача, которая породила эту по другому решается? Зачем вам такой поиск и хитрые непонятные объекты?
Лучше обсудить конкретно эту проблему, т.к., на мой взгляд она довольно общая и реальные задачи к ней могут сводиться.
Конкретно мой случай - это костыль к системе эвентов as3. Чтобы корректно освободить объект, приходится отписываться ото всех событий, которые он слушает. И я уже неоднократно напарывался на ситуации, когда освободить забываешь. И, казалось бы, уже несуществующий объект продолжает получать сообщения, делать что-то в системе и тем самым нарушать логику работы самым непредсказуемым образом. Хотелось механизма, который будет помнить все подписанные события и вызовом одной функции отписываться ото всех событий. Подписка на событие задаётся тремя элементами: EventDispatcher, String и Function. Я сделал вот такой объект, который хранит уникальную комбинацию для каждого подписанного события:
Код AS3:
	public class ListenerElem 
	{
		public var s: EventDispatcher;
		public var t: String;
		public var f: Function;
		public function ListenerElem(s: EventDispatcher, t: String, f: Function) 
		{
			this.s = s;
			this.t = t;
			this.f = f;
		}
 
		public function free(): void {
			if (s != null) {
				s.removeEventListener(t, f);
			}
			s = null;
			t = null;
			f = null;
		}
 
	}
И для их хранения сделал вот такое хранилище:
Код AS3:
	public class ListenerRegistry 
	{
		public var listeners: Vector.<ListenerElem> = new Vector.<ListenerElem>();		// TODO посмотреть, может стоит заменить на Dictionary с ключами-диспатчерами
		public function add(e: EventDispatcher, t: String, f: Function): void {
			//var l: ListenerElem = new ListenerElem(e, t, f);
			if ( indexOf(e, t, f) == -1) {
				listeners.push( new ListenerElem(e, t, f) );
				e.addEventListener(t, f);
			}
			else {
				trace('dublicate listener in registry, type: ' + t);
			}
		}
 
		public function del(e: EventDispatcher, t: String, f: Function): void {
			//var l: ListenerElem = new ListenerElem(e, t, f);		// TODO сработает ли?!
			var index: int = indexOf(e, t, f);
			if (index != -1) {
				listeners.splice(index, 1);
				e.removeEventListener(t, f);
			}
			else {
				trace('cant find listener in registry, type: ' + t);
			}
		}
 
		public function delAll(): void {
			var l: ListenerElem;
			while ( l = listeners.pop() ) {
				l.free();
			}
		}
 
		public function indexOf(e: EventDispatcher, t: String, f: Function): int {
			var i: String;
			for (i in listeners) {
				if (	(listeners[i]).s == e
				&&		(listeners[i]).t == t
				&&		(listeners[i]).f == f) {
					return i as int;
				}
			}
			return -1;
		}
 
		public function ListenerRegistry() 
		{
		}
 
	}
И теперь я могу очень легко контролировать отписывание от событий:
Код AS3:
 
	public class MyMovieClip extends MovieClip 
	{
		public var listeners: ListenerRegistry = new ListenerRegistry();
		public function MyMovieClip() 
		{
			listeners.add(this, Event.ADDED_TO_STAGE, init);
			listeners.add(this, Event.ENTER_FRAME, tick);
		}
 
		public function init(e: Event): void {
 
			listeners.del(this, Event.ADDED_TO_STAGE, init);
			// какой-то код инициализации
		}
 
		public function tick(e: Event): void {
			// какая-то циклическая работа 
		}
 
		// объект надо удалить
		public function free(): void {
			listeners.delAll();
		}
	}