-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();
}
}