« 外部swfの削除はLoader.unloadは使わない方が良いんじゃないかという件 | Home | TweenerのaddCallerをクリアする »

Apr 062008

外部swfの削除はLoader.unloadは使わない方が良いんじゃないかという件に誤りがあった件

ここ数日色々やってきましたが、
apeirophobia: Loader.removeChildapeirophobia: 外部swfの削除はLoader.unloadは使わない方が良いんじゃないかという件


Loader.unloadの処理にミスがありました・・・。(恥ずかしい・・・)


apeirophobia: Loader.removeChildの方でテストしていたスクリプトで

	_loader.unload();
	_loader= null;
となっている部分。これunloadでlodar.contentsが非表示になるのでうっかりしていたのですが、loader自体がremoveChildされていませんでした・・・orz。 ということで
	_world.unload();
	removeChild(_world);
	_world = null;
としてもう一度検証してみました。 以下その結果。

080406_e1.jpg
最初:6275kb
080406_e2.jpg
2500回目:7172kb。
080406_e3.jpg
5000回目:10572kb。
080406_e4.jpg
7500回目:8217kb。
080406_e5.jpg
10000回目終了:9900kb。

うん。問題なくできました・・・。すんません。

一応検証に用いたソース

var bt1 = new bt();
addChild(bt1);
bt1.addEventListener(flash.events.MouseEvent.CLICK,loadStart);
var bt2 = new bt();
bt2.x = 50;
bt2.addEventListener(flash.events.MouseEvent.CLICK,unloadExternal);
addChild(bt2);
//
var _loader:Loader;
var count:uint = 0;
var count2:uint = 0;
tx.text = String(count2);
//timer
var timer:Timer = new Timer(4000,1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE,loadStart);
function loadStart(e) {
	count=0;
	loadExternal();
}
function loadExternal(e=null) {
	var request:URLRequest = new URLRequest("dummy.swf");
	_loader = new Loader();
	addChildAt(_loader,0);
	var dispatcher = _loader.contentLoaderInfo;
	dispatcher.addEventListener(ProgressEvent.PROGRESS, onProgress);
	dispatcher.addEventListener(flash.events.Event.COMPLETE, onComplete);
	_loader.load(request);
}
function onComplete(e) {
	unloadExternal();
}
function onProgress(e) {
	//trace("progressHandler",e);
}
function unloadExternal(e=null) {
	var dispatcher = _loader.contentLoaderInfo;
	dispatcher.removeEventListener(ProgressEvent.PROGRESS, onProgress);
	dispatcher.removeEventListener(flash.events.Event.COMPLETE, onComplete);
	_loader.unload();
	removeChild(_loader);
	_loader = null;
	if (++count<100) {
		loadExternal();
	} else if (++count2<100) {
		tx.text = String(count2);
		timer.start();
		//System.gc();
	} else {
	}//System.gc();
}

個人的に外部swfを一度removeChildして、再利用という使い方をしないのででさほどEvent.REMOVED_FROM_STAGEでも問題はないのだけど、もしremoveChildして再度addChildして利用する場合はEvent.REMOVED_FROM_STAGEだと駄目。Event.REMOVEDだとその辺うまく切り分けられるのかしらね??そこはまだ検証してないけど・・・。

もし再利用するのであればEvent.UNLOADで処理。で、そのネストしている子供たちに何かしら明示的なメソッドで自分を掃除させる感じかなあ?ちょっとそれは面倒だなあ・・・。Event.UNLOADってその子供にも継承されないのかしら?

3 Comments

ちょっと気になることが一つ。
Event.REMOVED_FROM_STAGE
をListenして自分の掃除をさせる場合
parent.removeChild(this);
をするとGCが発動しないような気がする。
子供に対して
removeChildもchild = null;
も適応しない方がきれいにメモリがクリアされるような傾向が見られるのだけど、なんつーかタイミング的にGCが作動してないだけなのか?の判断が付かないので確証が持てない・・・。

でも検証の傾向としてはそんな感じがするであります。

この前の、ガベージコレクションウォッチャーを実装してくださった方がいるみたいですー。

http://d.hatena.ne.jp/kkanda/20080406

これで大分、メモリリーク対策も立てやすくなりそうです。

おぉ、ありがとうございますーー。

Leave a comment

Search and Archives