サイトトップ

Director Flash 書籍 業務内容 プロフィール

Macromedia Flash非公式テクニカルノート

StarlingフレームワークのEventDispatcher.dispatchEventWith()メソッドと新しいイベント配信

ID: FN1209002 Platform: All Version: CS6/ActionScript 3.0 Runtime: Flash Player 11/AIR 3.0

EventDispatcherクラス
パッケージ starling.events
継承 EventDispatcher → Object
dispatchEventWith()メソッド
文法 public function dispatchEventWith(type:String, bubbles:Boolean = false, data:Object = null):void
概要 第1引数で定めたイベントに登録されているリスナーすべてに、メソッドが受取った引数が納められたイベントを配信する。メソッドは内部的にプールされたイベントオブジェクトを使い回す。
引数

type:String − イベントのタイプを示す文字列。

bubbles:Boolean − バブリングイベントかどうかを示すブール(論理)値。イベントがバブルできるときはtrue、できない場合にはfalse(デフォルト値)を渡す。

data:Object − イベントオブジェクトに加えることができる任意の値。デフォルト値はnull

戻り値 なし。
Eventクラス
パッケージ starling.events
継承 Event → Object
Event()コンストラクタ
文法 public function Event(type:String, bubbles:Boolean = false, data:Object = null)
概要 リスナーに渡す新たなEventオブジェクトをつくる。
引数

type:String − イベントのタイプを示す文字列。

bubbles:Boolean − バブリングイベントかどうかを示すブール(論理)値。イベントがバブルできるときはtrue、できない場合にはfalse(デフォルト値)を渡す。

data:Object − Eventオブジェクトに加えることができる任意の値。デフォルト値はnull

dataプロパティ
文法 data:Object
プロパティ値 [読取り専用] Eventオブジェクトに加えることができる任意の値。
実装 public function get data():Object

説明
EventDispatcher.dispatchEventWith()は、EventDispatcher.dispatchEvent()と同じく、リスナーにイベントを配信するメソッドです。ただし、引数が少し異なり、新たな機能がふたつ加わっています。

第1の機能は、引数に関わります。EventDispatcher.dispatchEventWith()メソッドの初めのふたつの引数は、Event()コンストラクタに渡すのと同じ、イベントのタイプとバブリングの指定です。新しい機能は第3の引数で、任意のデータが渡せます。その値は、イベントオブジェクトに納められるので、リスナーが取出して使えます。これまでは定義済みのActionScript 3.0も含め、イベントオブジェクトに加えたいデータがあるときは、Eventクラスのサブクラスを定めなければなりませんでした。Starlingフレームワークでは、その手間が省けるのです。

引数についてはもうひとつ、EventDispatcher.dispatchEventWith()メソッド第1引数がイベントタイプの文字列で、EventDispatcher.dispatchEvent()のようなイベントオブジェクトではありません。つまり、メソッドでイベントを配信するたびに、新たなイベントオブジェクトをつくらずに済みます。

オブジェクト.dispatchEventWith(イベント);

オブジェクト.dispatchEvent(new Event(イベント));

EventDispatcher.dispatchEventWith()メソッドの第3引数に与えた値は、リスナーが受取ったイベントオブジェクトの読取り専用プロパティEvent.dataとして取出せます。さらに、イベントリスナーの引数はふたつに増え、それらを省くこともできるようになりました。

addEventListener("customType", onEvent);
dispatchEventWith("customType", false, "testData");

// [例 1]:
function onEvent():void {
  // 引数なしでイベントのみ捉える
}

// [例 2]:
function onEvent(event:Event):void {
  // Event.dataプロパティを取出す
  trace(event.data); // 出力: testData
}

// [例 3]:
function onEvent(event:Event, data:Object):void {
  // 引数で追加データを受取る
  trace(data); // 出力: testData
}

EventDispatcher.dispatchEventWith()メソッドに加えられた第2の新しい機能は、イベントオブジェクトの使い回しです。これは、スクリプティングに用いる機能ではなく、内部的な処理の最適化です。前述のとおり、メソッドの第1引数には、イベントオブジェクトではなく、イベントタイプの文字列を渡します。これは、すでにつくったインスタンスはEventオブジェクトの中にとっておき、つぎにインスタンスが要るときは、それをリセットして使い回すためです。

一般に、オブジェクトは新たにつくるより、設定を変えて使い回す方が処理は速くなります。さらに、要らなくなったオブジェクトをメモリから消す「ガベージコレクション」という仕組みは負荷が高く、小分けされて働きます[*1]。すると、ガベージコレクションが済むまでは、要らないオブジェクトがメモリに居座ることになります。オブジェクトを使い回せば、ガベージコレクションの手間を減らすことができるのです。

なお、EventDispatcher.dispatchEventWith()メソッドで配信するのでない、定義済みのイベントについてもリスナーが受取る引数について改善されています。

addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
function onAddedToStage():void {
  // イベントオブジェクトを使わないなら引数は省ける
}

addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(event:Event, passedTime:Number):void {
  // 第2引数のpassedTimeで経過時間がわかる
}

addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
function onKeyDown(event:Event, keyCode:uint):void {
  // 第2引数のkeyCodeでキーコードがわかる
}

[*1] ガベージコレクションについては、「System.pauseForGCIfCollectionImminent()メソッド」をご参照ください。


実装
EventDispatcher.dispatchEventWith()メソッドの実装を見ましょう。静的メソッドEvent.fromPool()で、引数値が定められたEventオブジェクトを得て、EventDispatcher.dispatchEvent()に渡して呼出し、Event.toPool()メソッドでそのオブジェクトを戻しています。このEventクラスのふたつの静的メソッドが、オブジェクトを使い回します。

public class EventDispatcher {
  // ...[中略]...
  public function dispatchEventWith(type:String, bubbles:Boolean = false, data:Object = null):void {
    if (bubbles || hasEventListener(type)) {
        var event:Event = Event.fromPool(type, bubbles, data);
        dispatchEvent(event);
        Event.toPool(event);
    }
  }
  // ...[中略]...
}

Event.fromPool()メソッドは、すでにつくられたイベントオブジェクトがあれば、それをリセットして返します。reset()メソッドは、オブジェクトのもつ値を設定し直します。そして、Event.toPool()メソッドは、イベントオブジェクトをVectorオブジェクト(sEventPool)に加えてとっておきます[*2]。このようにオブジェクトをとっておいて使い回す仕組みは「オブジェクトプーリング」と呼ばれます。

public class Event {
  // ...[中略]...
  private static var sEventPool:Vector.<Event> = new <Event>[];
  private var mTarget:EventDispatcher;
  private var mCurrentTarget:EventDispatcher;
  private var mType:String;
  private var mBubbles:Boolean;
  private var mStopsPropagation:Boolean;
  private var mStopsImmediatePropagation:Boolean;
  private var mData:Object;
  // ...[中略]...
  public function Event(type:String, bubbles:Boolean = false, data:Object = null) {
    mType = type;
    mBubbles = bubbles;
    mData = data;
  }
  // ...[中略]...
  public function get data():Object { return mData; }
  // ...[中略]...
  starling_internal static function fromPool(type:String, bubbles:Boolean = false, data:Object = null):Event {
    if (sEventPool.length) return sEventPool.pop().reset(type, bubbles, data);
    else return new Event(type, bubbles, data);
  }
  starling_internal static function toPool(event:Event):void {
    event.mData = event.mTarget = event.mCurrentTarget = null;
    sEventPool.push(event);
  }
  starling_internal function reset(type:String, bubbles:Boolean = false, data:Object = null):Event {
    mType = type;
    mBubbles = bubbles;
    mData = data;
    mTarget = mCurrentTarget = null;
    mStopsPropagation = mStopsImmediatePropagation = false;
    return this;
  }
  // ...[中略]...
}

[*2] starling_internalは、starling.coreパッケージに定められた名前空間です。決まった他のクラスからのみ参照できるように設けられた非ドキュメントの名前空間です。将来のバージョンのStarlingでは除かれる可能性があります。


参考
[Starling Framework Reference] > [EventDispatcher]「dispatchEventWith() method
[Starling Framework Reference] > [Event]


作成者: 野中文雄
作成日: 2012年9月1日


Copyright © 2001-2012 Fumio Nonaka.  All rights reserved.