3

Android 用の Titanium ベースのモバイル アプリケーションでメモリ リークを制御する方法について説明している多くの Web ページを読みました。

私の状況では、ユーザーがナビゲートできる複数レベルのリスト (実際にはこれらは tableViews) を使用するアプリを構築しています。1 つのウィンドウを使用しており、ユーザーがリスト項目を選択すると、右から左にアニメーション化される新しいビューが作成されます。すべてのプラットフォームで右から左にスライドする新しいウィンドウを作成することは不可能に思われたため、このオプションを選択しました。

すべてのビューで、どの tableRow がクリックされたかを確認するために eventListener が作成され、対応するサブメニューが作成されて画面にアニメーション化されます。

ビューをクリックするたびにメモリ使用量が着実に増加していることに気付きましたが、メモリリークがどこにあるかを特定できないようです。

現在、メイン ウィンドウをチェックして、ウィンドウがアニメーション表示されていないかどうかを確認しています (320px 幅のデバイスでは .left プロパティは 320 です)。次に、このビューをウィンドウから削除し、次を使用してプロキシを null に設定します。

for ( i = 0; i < win.children.length; i++) {
    if ( (win.children[i] != null) && (win.children[i].left == 320) ) {
        win.remove(win.children[i]);
        win.children[i] = null;
    }
}

ただし、メモリ使用量はまだ増加しています。これは、次を含む関数を使用して、すべての新しいビューにテーブルとイベント リスナーが含まれていることが原因である可能性があります。

var sub_table = Ti.UI.createTableView({top:'50dp',separatorColor: rowSeparatorColor});  
sub_table.setData(data);
sub_table.addEventListener('click', function(e) {
    create(e.rowData.data);
}); 
new_view.add(my_navbar);
new_view.add(sub_table);
return new_view;

それらを個別に消去する必要がありますか、それともビューが破棄されたときに破棄されますか? それらを手動で消去する必要があるのですが、どうすればよいですか?

より一般的なメモとして、メモリ使用量の原因を特定する方法がわかりません。特定の時点でメモリ内にあるすべてのオブジェクトや変数を取得する方法はありますか? Dalvik ツールキットが提供するメモリ使用量をドリルダウンする方法はありますか? すべてのグローバル変数またはイベント リスナーを取得する方法はありますか?

4

3 に答える 3

1

私は Android メモリ マネージャーを使用したことがなく、Apple Instruments アプリのみを使用しました。

まず最初に、アプリを全体としてではなく、部分的に見ることです。メイン ウィンドウのコードを 1 行ずつ調べて、既知のメモリの問題をすべて排除しました。メイン ウィンドウで基準となる数のオブジェクトを取得し、それを使用してアプリ内の他のウィンドウと比較することができました。次に、これらのウィンドウ間を移動し、割り当てられたオブジェクトの数が毎回ベースラインに戻ることを期待して、すべてのメモリの問題を解決します。

たとえば、メイン ウィンドウを開くと、2 つのボタンと 2 つのラベルが割り当てられることを期待します。次のウィンドウに移動すると、2 つのボタンと 2 つのラベルが表示されます。これらのオブジェクトの数が 4 と 4 にジャンプすることを期待します。次に、メイン ウィンドウに戻り、もう一方のウィンドウを閉じます。2 が表示されることを期待します。追加のボタンとラベルは最終的にクリーンアップされます。すぐにではないので、更新するか監視して、それらが消えることを確認します.

コードの大部分をコメントアウトして、それが原因かどうかを確認できることを覚えておいてください。たとえば、コードにリークがあると思われる場合は、そのコードをコメントアウトして、オブジェクト インスタンスの数が期待どおりに増減するかどうかを確認します。

ウィンドウを閉じると、適切に宣言されていれば、割り当てられたすべてのオブジェクトが最終的にクリーンアップされることがわかりました。変数の 1 ~ 2 例で「var」キーワードが欠落していることがわかりました。それらはグローバル スコープで宣言されていると思われるので、クリーンアップしました。

私は自分で助けを求めてAppceleratorのフォーラムに投稿しました。ここに私の投稿があり ます。

この投稿には、いくつかの提案と、アプリのデバッグについて説明している Appcelerator によるビデオへのリンクがあります。

于 2013-03-07T20:09:02.277 に答える
0

そして、このようなものも機能しますか?この場合、リスナーをセットアップし、リスナーをテーブルにアタッチします。テーブルをクリックすると、リスナーが削除され、create() メソッドを使用して新しいテーブルが作成されます。それは一種の再帰的に機能し (テーブルがクリックされた後に create() 関数がそれ自体を呼び出します)、疑問が残ります。しかし、eventListener を削除し、ウィンドウからビューを削除し、そのプロキシをゼロに設定する必要がありますか?

function create(i) {
    var listener = function(e) {
        win.removeEventListener('click', listener);
        win.remove(clickedview);
        clickedview = null;
        create(e.rowData.data);
    }
    var sub_table = Ti.UI.createTableView({top:'50dp',separatorColor: rowSeparatorColor});  
    sub_table.setData(data);
    sub_table.addEventListener('click', listener);
    new_view = populateView(i);
    new_view.add(sub_table);
}
于 2013-03-06T16:48:15.323 に答える