« 交流会 | Home | Loaderの読み込み強制終了 Loader.unload編 »

Nov 162008

Loaderの読み込み強制終了 Loader.close編

外部イメージのローディング途中で他の処理やシーンに遷移したい場合等、ローディングを任意に中止する部分で現在はまり中ということで検証を時系列的にメモ。

"Loader"クラスには"close"と"unload"という似たようなメソッドが2つほどある。

closeは

Loader インスタンスに対して現在進行中の load() メソッドの処理をキャンセルします。

一方unloadは

load() メソッドを使用してロードされた、この Loader オブジェクトの子を削除します。関連したLoaderInfo オブジェクトの property は null にリセットされます。他のオブジェクトが参照している可能性があるため、子は必ずしも破棄されるとは限りません。ただし、Loader オブジェクトの子ではなくなります。

と定義されている。

とりあえず"close"から検証してみる。
CODE:1

_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.OPEN, function() { trace("ロード開始");} );
_loader.contentLoaderInfo.addEventListener(Event.UNLOAD, function(){trace("アンロードされました")});
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _loaded_Loader);
・・・
//キャンセルボタン(※CastButtonを使用)
_bt_cancel.onCastMouseDown = function(){ _loader.close(); }
・・・
private function _loaded_Loader(e:Event):void
{
	trace("ロード完了");
	addChildAt(_loader,0);
}

既にこの時点でCLOSEイベントを取得する口が見つからない(汗 EVENT.CLOSEは"Socket","XMLSocket"だけにしか用意されていないイベント。つまり発動したとしても結果を拾えないという謎な感じになっている。

とりあえずプレビュー/ダウンロードシミュレートで実行、

1:読み込み中にclose実行>何事も無かったかの様に読み込み完了+表示。
2:読み込み終了後にclose実行>Error: Error #2029: この URLStream オブジェクトには開いているストリームがありません。(読み込み前も同じ)

一体何をしてくれているのか良く分かりません。とりあえずサーバにアップしてhttp経由での動作も確認してみます。(帯域は100kb/sに絞って、通信内容をプロクシで拾います)

1:読み込み中にclose実行>少しタイムラグはありますが、読み込みを途中で中断。
2:読み込み終了後にclose実行>Error: Error #2029: この URLStream オブジェクトには開いているストリームがありません。(読み込み前も同じ)

ということでhttp経由でストリーム状態になっていないと動作しないメソッドのようです。またストリーム状態になっていないと例外がthrowされるので、そこらへんイベントとしてきちんと取得することができないのか?を試してみます。

_loader.contentLoaderInfo.addEventListener(Event.CLOSE, function() { trace("クローズされました"); _output.text = "contentLoaderInfo.CLOSED"; } );
_loader.addEventListener(Event.CLOSE, function() { trace("クローズされました"); _output.text = "loader.CLOSED"; } );
を追加してみましたが、両方とも取得できず。 ということでやはりEVENT.CLOSEはLoaderでは取得できないようです。

ではcloseをCALLする際に例外を回避するためにどすれば良いのか?クラス的に考えればLoaderクラスを拡張してLoading状況をフラグで持たせるのがスマートな方法ですが(progressionでは実装されている)、ここではLoaderInfo標準のプロパティbytesLoaded,bytesTotalを使ってみます。close処理の部分を以下のように変更。
CODE:2

_bt_cancel.onCastMouseDown = function()
{
	if (!_loader.contentLoaderInfo) return;
	if (_loader.contentLoaderInfo.bytesLoaded == _loader.contentLoaderInfo.bytesTotal)return
	_loader.close();
}
実行した結果は

1:読み込み前にclose>エラーは出ない 2:読み込み中にclose>読み込み中断してくれる。 3:読み込み後にclose>エラーでない。_loaderはそのまま表示。 4:読み込み中にcloseして中断後、再度close>Error: Error #2029: この URLStream オブジェクトには開いているストリームがありません。

ということで、これはcloseではcontentLoaderInfoがクリアされていないということなのだろうということで以下のように変更。 CODE:3

_bt_cancel.onCastMouseDown = function()
{
	if (_loader.contentLoaderInfo && _loader.contentLoaderInfo.bytesLoaded < _loader.contentLoaderInfo.bytesTotal)
	{
		_loader.close();
	}
	_loader.unload();
}
実行結果は
1:読み込み前にclose>エラーは出ない 2:読み込み中にclose>読み込み中断してくれる。 3:読み込み後にclose>エラーでない。_loaderも消去。 4:読み込み中にcloseして中断後、再度close>エラーでない。

という感じになりました。 ただちょっと気になるのはcloseのレスポンスがあまりよろしくない感じ。サーバの状況によるのだろうけど、closeをCALLしてからサーバからの読み込み処理をキャンセルするまでに若干のタイムラグがある。これがキャンセルされる前に読み込みが完了してしまったりするとまたちょっと工夫が必要になる場合もあるかもしれません。

ちなみにプレビュー環境では上記の記述をしてもcloseが作動しないため、読み込み中にclose,unloadの組み合わせで実行しても普通に読み込み完了して表示されます。これはちょっと分かりにくい・・・汗 特にCOMPLETEイベントが発動してしまうので、そこらへんで色々他のものと連動させたりしているとものすごくおかしな挙動をすると思います。なのでclose処理を行ったところでCOMPLETEイベントのリスナーを削除して、再度Loadする際にAddするとかそういう処理が必要になるかも知れません。

ということでcloseについて長々と書きましたが、結局unloadも使っているわけで、じゃあ、unloadだけで何とかなるんじゃないか?ということで、unloadだけを使っての検証を次のエントリーで行ってみます。

ちなみにPlayer ver.10から[234510]ActionScript 3 の Loader.unloadAndStop について(Flash Player 10)が実装されるので、外部SWF系の処理は今までよりも楽になるね。

Leave a comment

Search and Archives