外部swfの削除はLoader.unloadは使わない方が良いんじゃないかという件に誤りがあった件 [ Flash ]
ここ数日色々やってきましたが、
apeirophobia: Loader.removeChild、apeirophobia: 外部swfの削除はLoader.unloadは使わない方が良いんじゃないかという件
Loader.unloadの処理にミスがありました・・・。(恥ずかしい・・・)
apeirophobia: Loader.removeChildの方でテストしていたスクリプトで
_loader.unload();
_loader= null;となっている部分。これunloadでlodar.contentsが非表示になるのでうっかりしていたのですが、loader自体がremoveChildされていませんでした・・・orz。ということで
_world.unload();
removeChild(_world);
_world = null;としてもう一度検証してみました。以下その結果。

最初:6275kb

2500回目:7172kb。

5000回目:10572kb。

7500回目:8217kb。

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ってその子供にも継承されないのかしら?

コメント
ちょっと気になることが一つ。
Event.REMOVED_FROM_STAGE
をListenして自分の掃除をさせる場合
parent.removeChild(this);
をするとGCが発動しないような気がする。
子供に対して
removeChildもchild = null;
も適応しない方がきれいにメモリがクリアされるような傾向が見られるのだけど、なんつーかタイミング的にGCが作動してないだけなのか?の判断が付かないので確証が持てない・・・。
でも検証の傾向としてはそんな感じがするであります。
投稿者: +39 | 2008年04月07日 00:07
この前の、ガベージコレクションウォッチャーを実装してくださった方がいるみたいですー。
http://d.hatena.ne.jp/kkanda/20080406
これで大分、メモリリーク対策も立てやすくなりそうです。
投稿者: fladdict | 2008年04月09日 00:33
おぉ、ありがとうございますーー。
投稿者: +39 | 2008年04月09日 05:06