[AS3] DisplayObjectインスタンスの削除とガベージコレクション [Edit]

MovieClipシンボルのフレームアクションで親のタイムラインからインスタンスを消すには、つぎのようにDisplayObjectContainer.removeChild()メソッドを呼出します[*1][*2]。ただし、このとき気をつけなければならないことがあります。

var parent_mc:MovieClip = MovieClip(parent);
parent_mc.removeChild(this);

表示リストからの削除

このフレームアクションが、ループするフレームアニメーションの中のひとつのフレームに書かれていたとします。すると、つぎのようなランタイムエラー#1009が起こります。

TypeError: Error #1009: nullのオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。

なぜなら、DisplayObjectContainer.removeChild()メソッドは、親(DisplayObjectContainer)インスタンスの表示リストからインスタンスを除くだけで、メモリから消し去る訳ではありません。インスタンスがメモリに残っていれば、フレームループは続きます。

そして、上記フレームアクションが再び実行されたとき、インスタンスは表示リストに入っていないので、DisplayObject.parentプロパティの値はnullになります。nullはインスタンスの参照ではありません。したがって、インスタンスのメソッドを呼出すこともできない、というのがランタイムエラーの意味です。

このエラーを避けるには、フレームループは止める、つまりMovieClip.stop()メソッドを呼出すのがよいでしょう。もっとも、もはや要らないインスタンスであれば、メモリに残しておきたくありません。どうしたら削除できるでしょうか。

メモリからの削除

残念ながら、インスタンスをメモリから削除するメソッドというような直接的な手段は与えられていません[*3]。Flash Playerは、ActionScriptで使われている各オブジェクトへの参照を確かめ、すべての参照がなくなるとメモリを自動的に解放します。これは「ガベージコレクション」と呼ばれる仕組みです。

ガベージコレクションにインスタンスをメモリから片づけてもらうには、インスタンスへの参照をすべて消し去ることです。たとえば、インスタンスが変数・プロパティに納められているときは、nullを代入して参照を切ります。また、インスタンスの関数・メソッドがイベントリスナーに登録されていれば、それを削除します[*4]

ただし、すべての参照が失われたからといって、ただちにガベージコレクションが働く訳ではありません。ガベージコレクションは、負荷の少なくない処理です[*5]。そのため、Flash Playerの忙しさやメモリの空き具合によって、実行の度合いは変わってきます。

さらに、インスタンスが活動していないということも、ガベージコレクションが片づけるときに気づかうようです[*6]。そのためにも、インスタンスのフレームアニメーションは止めておく方がよいでしょう。


[*1] ステージにあるインスタンスを画面から消すには、いくつかのやり方があります。それらの得失については、Adobeデベロッパーセンター「ActionScript 3.0におけるパフォーマンス向上のヒント」の04「visibleとalphaとremoveChild()」をお読みください。

[*2] DisplayObject.parentプロパティの値は、DisplayObject型です。したがって、そのサブクラスのメソッド DisplayObjectContainer.removeChild()を呼出すには、参照はキャストしなければなりません。キャストについては、「rootプロパティでメインタイムラインの関数にアクセスできない」の「対処法」[2]「キャスト」をご参照ください。

[*3] Flash Playerのデバッグ版([ムービープレビュー]も含む)およびAIRアプリケーションでは、System.gc()メソッドでガベージコレクションを実行することができます。

[*4] なお、弱い参照について「EventDispatcher.addEventListener()メソッド 」をご参照ください。

[*5] akihiro kamijo「Flash Player 9 のガーベジコレクション」およびwww.imajuk.swf「ASのガベージコレクトは参照カウント方式じゃなかった」をご参照ください。

[*6] Colin Moock「The Official "visible vs alpha vs removeChild()" Showdown」は、「DisplayObjectは、活動や参照がなくなり、ガベージコレクションが働いて初めて、メモリから取除かれる」("Display objects are removed from memory only once they have been deactivated, dereferenced, and garbage collected.")と述べます。そして、公式の情報ではないものの、MovieClipインスタンスの再生は「活動」に含まれるとのことです(moockblog「Things You Must Do Before Unloading a SWF File」)。

コメント

この記事へのコメント

  1. 1.emt training(2010年12月20日 17:05)

    What a great resource!

この記事にコメントを書く

記事に対するテクニカルな質問はご遠慮ください(利用規約)。

その他の記事