Flex アプリケーションのプリローダーがローディングしているときにステージをクリックすると、SystemManager がランタイムエラーを発生する問題を発見しました。
この問題は、デフォルトのプリローダーを使用しても発生しますし、プリローダーのローディング時間が長ければ長いほど発生するリスクが増えます。
新規作成直後で最小状態の Flex アプリケーションでも、プリローダーが一瞬表示されるので、この隙にマウスを連打するなどしてステージをクリックすればアウトです。
原因は、SystemManager の 5649 行目です。
5646 : private function stageEventHandler(event:Event):void
5647 : {
5648 : if (event.target is Stage)
5649 : mouseCatcher.dispatchEvent(event);
5650 : }
mouseCatcher は、プリローダーのローディングが完了するまで NULL なのですが、stageEventHandler はプリローダー動作中も呼び出されます。つまり、mouseCatcher の NULL チェック漏れです。
この問題は Gumbo にもあったようで、Flex 4 では fix されています。
https://bugs.adobe.com/jira/browse/SDK-22682
当面の回避策
プリローダークラスを自作して、ステージの MouseEvent.MOUSE_DOWN イベントを SystemManager 内のリスナーより早く拾って、イベントの伝播を止める。
面倒だと感じる方は、以下のように DownloadProgressBar クラスを継承することをおすすめします。
package {
import flash.events.Event;
import flash.events.MouseEvent;
import mx.preloaders.DownloadProgressBar;
public class MyPreloader extends DownloadProgressBar {
public function MyPreloader() {
super();
addEventListener(Event.COMPLETE, onCompleteHandler);
addEventListener(Event.ADDED_TO_STAGE, addedToStateHandler, false, int.MAX_VALUE, true);
}
protected function addedToStateHandler(event:Event):void {
stage.addEventListener(MouseEvent.MOUSE_DOWN, stageMouseDownHandler, false, int.MAX_VALUE, true);
removeEventListener(event.type, arguments.callee);
}
protected function stageMouseDownHandler(event:MouseEvent):void {
event.stopImmediatePropagation();
}
protected function onCompleteHandler(event:Event):void {
stage.removeEventListener(MouseEvent.MOUSE_DOWN, stageMouseDownHandler, false);
removeEventListener(event.type, arguments.callee);
}
}
}