カメラを起動してバーコードを撮影し、そこから読み取ったISBNコードを使ってAmazonAPIを叩いたり何だりするアプリを作ったものの、やたらと落ちる。
そんなときに行った対処法です。
HTTP通信
APIを叩くときなど使用頻度の高いHTTP通信ですが、Titanium.Network.HTTPClientを使ったときにメモリリークが多発。
原因:単純に通信後メモリ解放が出来ていない
解決:通信終了後にonloadなどのコールバックメソッドにnullを渡してあげる
ということで、以下のように実装しました。
var client = Ti.Network.createHTTPClient({
onload : function(e) {
/*
* 無事レスポンスが返ってきたときの処理
* ex) nextScreen関数に返ってきたテキストを渡す
*/
nextScreen(this.responseText);
/* nullを渡してコールバックメソッドの解放 */
client.onreadystatechange = null;
client.onload = null;
/* HTTPClient自身にも */
client = null;
},
onerror : function(e) {
/* エラー時のステータス出力 */
Ti.API.info('error: ' + e.source.status);
/* nullを渡してコールバックメソッドの解放 */
client.onreadystatechange = null;
client.onerror = null;
/* HTTPClient自身にも */
client = null;
},
/* タイムアウト設定(1ミリ秒) */
timeout: 1000
});
/* ついでにロード画面 */
client.onreadystatechange = function() {
if (this.readyState == 2) {
$.loadImage.backgroundImage = "/img/画像ファイル";
}
};
参考
- Titaniumでネットワーク周りのメモリリークを回避する/M.P.B.
EventListener
次に取りかかったのがEventListenerの見直し。
イベントリスナーを追加した場合、イベント終了時にイベントを削除する必要があるとのこと。
原因:イベントがずっと生きている
解決:用の済んだイベントを削除
ダイアログを例にとると、このように実装しました。
var arr = ["first", "secont", "third"];
var dialog = Titanium.UI.createOptionDialog();
/* ダイアログのタイトルとオプション(選択肢)をセット */
dialog.setTitle('ダイアログタイトル');
dialog.setOptions(arr);
/* オプションが選択されたときの処理 */
dialog.addEventListener('click', function(event) {
number = event.index;
/* イベントリスナーの削除 */
dialog.removeEventListener("click", arguments.callee);
});
参考
- Documentation Guides - Managing Memory and Finding Leaks
画面遷移
画面遷移というか、結果として画面遷移に関係する形で解決したもの。
原因:ISBN読み込む→必要な情報取得→画面遷移&表示 の流れが早過ぎて忙しくなった
解決:余計な処理を間に挟む
画面遷移時に0.5秒のインターバルを設けました。
function openAndClose(controller){
/* 0.5秒経過したら次の画面に遷移し、今の画面を閉じる */
setTimeout(function(){
nextScreen.open();
$.Screen.close();
}, 500);
}
と、書いたもののfireEvent使えば余計な処理書かずに解決出来るらしいので、今度実装してみようかと思います。