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