AS3のLoaderで読み込んだ外部swfを確実にunloadする方法
公式サイトのFAQやリファレンスには、子swfがストリームを利用している場合のunload方法が紹介されています。
- Loader インスタンスを unload しても NetStream が閉じられない(support.adobe.co.jp)
が、私の場合はストリームを利用していなくてもunloadでswfが破棄されず、メモリリークが発生する現象が発生。1週間ほど苦しんだ末にやっと以下の方法で解決できました。
- unload時に、子swf内のイベントリスナーを全てremoveする
- unload時に、子swf内のクラス変数の中で、オブジェクトを参照しているもの全てにnullを代入する
この対処をしないと破棄されないswfの正確な条件はまだ良く分かりませんが、とりあえず手元にあるやつだとPapervision3Dを利用しているものにこの対処が必要でした。
Loaderオブジェクトへの参照があるとガベージコレクトされないのは分かるけど、その中のものまで掃除しなきゃいけないってのが謎です。
子swfでのstage参照
もうひとつ注意点。unloadが送出された時には子swfのstageはnullになっています。そのためstageに直接リスナーを追加していると削除できないリスナーが残ってしまいます。なので、stageにリスナーを追加したい場合は、stageに直接ではなく、stageへの参照を用意してそれに追加するようにすればオッケーです。
参考サイト
- blog.nium.jp | 通常読み込みと外部SWF読み込みの処理の違い
実はまずこれに引っかかりました - akihiro kamijo: Flash Player 9 のガーベジコレクション
分かりやすい解説 - Loader - ActionScript 3.0 コンポーネントリファレンスガイド
Loaderクラスの公式リファレンス - justGREAT ≫ Blog Archive ≫ Garbage Collector troubles using the Loader class.
やはりLoaderクラスでメモリリークに遭遇した人 - gskinner.com: gBlog: AS3: Resource Management pt 3
強制GCのHackが紹介されているが、今回の件では役に立たなかった