2013年03月13日

【AIR】モバイル紙芝居アプリでメモリ使用量を減らす作業した

airflash
完成間近のAIRアプリなんだけど実機テストしたらメモリ使用量が増加し続けてまともに動かない助けて!という依頼を受けて、傭兵やりました。社会人になって最初の大きなミスが、Flash Liteのメモリ使用量を無視して作ってて、多くの端末で画面真っ赤、俺(と社長)真っ青。ってやつだったので、とても人ごととは思えません。幸い今はStatsという素晴らしいモノがあるので、あの頃の自分を救うという意味でも、出来るだけスマートに作業したい所。

調べたところ、イベント割当や変数代入といった参照を消したBitmapDataをdispose()する事で、メモリの解放を促せる(ガベージコレクト対象になる)という事のようです。bitmapをremoveするだけじゃ解放されないって事です。問題の.flaファイルは山ほどのBitmapをタイムライン上でステージに配置&トゥイーン、ASは各階層の各キーフレームに書いてあるといった状態だったので、まずはASをルートに整理して、全体の見通しを良くしました。これはぜひやった方が良いと思います。全部整理は出来なくても、出来る限りやった方が良いです。

で、disposeについて。AS整理してaddEventListenerとremoveEventListenerを一括管理するようにしたので、イベント割当は確実に消せているはずです。それが出来たら、ステージに配置したBitmapにASからアクセス出来れば、基本的にはASの修正だけで済むんじゃないかなと考えました。で、以下の感じ。手元にファイルが無いので、考え方のイメージだけ持ってもらえれば。事前作業として、ライブラリに格納してあるbitmapのプロパティで、ActionScriptに書き出し、1フレーム目に書き出し、基本クラス→flash.display.BitmapData にして下さい。これをせずにステージに配置したBitmapはShapeに分解されちゃうようです。


var bitmapArr:Array=[];

addEventListener(Event.ADDED,pickupBitmap()); //ステージに配置されたらイベント

function pickupBitmap(e){
if(e.target is Bitmap){
bitmapArr.push(e.target); //bitmapだったら配列に追加
};
};

// 適当なタイミングで以下を呼び出す
function disposeBitmapData(e){
for (var i:String in bitmapArr) {
bitmapArr[i].bitmapData.dispose(); //bitmapの中のbitmapDataにアクセス
bitmapArr[i]=null; //念のため
}
bitmapArr=[]; //disposeが終わったら配列初期化
};

※タイムラインにキーフレーム打って配置 = addChild();
 そのレイヤーにキーフレーム打って削除、空白レイヤーにする = removeChild();
になるようなので、disposeする前に空っぽなフレームに飛ばすか、キーフレーム打って空白にする必要があります。

ポイントは、タイムラインに縦横無尽に配置されているBitmapを軒並み拾うために、ADDEDイベントを使う事です。そこまでに配置したbitmapを全部解放対象にしちゃうので、disposeのタイミングは注意して下さい。AIRの場合はSystem.gc();で強制的にガベージコレクタ起動出来る様ですが、基本的にタイミングはシステム任せで、大きなきっかけの時のみ呼ぶようにしました。今一ガベージコレクタって、挙動が安定しないというか、使い勝手が微妙に悪いような...弱参照とか、曖昧で信用ならんし。

タイムラインに配置したインスタンスをASで操作するとか、goto文やキーフレーム、シンボル名とイベント処理を並列させるとかなるべくやりたくないですが、とはいえFlashの柔軟なタイムラインは使いどころ間違えなければ強力ですので、毛嫌いせず柔軟に対応出来たら良いのかなと思いました。

sarustar at 02:03│Comments(0)TrackBack(0)このエントリーをはてなブックマークに追加 mixiチェック Clip to Evernote ActionScript3 




トラックバックURL

>

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔