removeEventListener の拡張

EventDispatcher.removeEventListener の第 2 引数には対象リスナへの参照が必要だが、ある関数内のローカル変数としてリスナを作成し登録してしまうと、関数を抜けた後、つまり参照を失った際に、そのリスナの解除が困難となる。

幸いにも (というか実装上)、EventDispatcher は、個々のイベントに対するリスナの一覧を内部で保持している。参照を失ったリスナを解除するには、そのリストごと破棄すればよい。勿論、他のリスナも解除されてしまうので注意。

以下は、EventDispatcher を継承した EventDispatcherExtended クラスの例。removeEventListener のみオーバーライドしている。第 2 引数が空ならば、全てのリスナを削除する。

import mx.events.EventDispatcher;
/**
*  mx.events.EventDispatcher の拡張
*/
class org.dyndns.bitmap.events.EventDispatcherExtended extends EventDispatcher {
/**
*  コンストラクタ
*/
private function EventDispatcherExtended() {}
/**
*  リスナを削除する
*  @param event    イベント名
*  @param listener イベントリスナ
*/
public function removeEventListener(event:String, listener:Object):Void {
//リスナが指定されていれば通常の動作
if ((event != null) && (listener != null)) {
super(event, listener);
//リスナが指定されていなければ全て削除
} else if ((event != null) && (listener == null)) {
delete this["__q_" + event];
}
}
}

例として、EventDispatcherExtended を継承した Hoge クラスを定義する。

import org.dyndns.bitmap.events.EventDispatcherExtended;
/**
*  Hoge
*/
class Hoge extends EventDispatcherExtended {
/**
*  コンストラクタ
*/
public function Hoge() { }
/**
*  テスト
*/
public function test():Void {
var eventObject:Object = new Object();
eventObject.type = "onTest";
//イベントを配信する
this.dispatchEvent(eventObject);
}
}

クライアントは Hogeインスタンスを持ち、listenHoge で Hoge.onTest イベントに対してローカル変数のリスナを登録する。また、releaseHoge では Hoge.onTest に対する全てのリスナを解除する。

import Hoge;
/**
*  クライアント
*/
class Client {
private var hoge:Hoge = null;
/**
*  コンストラクタ
*/
public function Client() {
this.hoge = new Hoge();
}
/**
*  hoge をリスンする
*/
public function listenHoge():Void {
var listener:Object = new Object();
listener.onTest = function():Void {
trace("test");
};
this.hoge.addEventListener("onTest", listener);
}
/**
*  hoge のリスンを解除する
*/
public function releaseHoge():Void {
this.hoge.removeEventListener("onTest");
}
/**
*  実行
*/
public function fire():Void {
this.hoge.test();
}
}

テストコード。

import Client;
var client:Client = new Client();
this.client.listenHoge();
this.client.listenHoge();
this.client.listenHoge();
this.client.fire();
this.client.releaseHoge();
trace("released");
this.client.listenHoge();
this.client.fire();

実行結果。ローカル変数のリスナを解除していることが判る。

test
test
test
released
test