web-dev-qa-db-ja.com

Androidヒープサイズについて

Android開発にかなり慣れていないので、Java Out of Memory例外。アプリがなくなったことを意味します。 VM予算以上ですが、何度もグーグルで調べた後、私はまだこの概念を把握していないようです。画面ごとに6つのボタンセレクタがあるため、アプリがメモリを使いすぎているのではないか各セレクタの2つのビットマップは、プロパティタブによると、それぞれ約20 kbです。ルート化されたG2xでは、VM予算を12mbに設定し、携帯電話を再起動し、問題なくアプリを実行しました。各onDestroy()でドロウアブルのバインドを解除し、GCもここで実行するようにヒントを出しますエミュレータでしばらくアプリを使用した後、DDMS画面で[Cause GC]をクリックすると、結果はID = 1、ヒープサイズになります。 6.133 MB、割り当て済み2.895MB、無料3.238 MB、使用率47.20、#オブジェクト52,623。

ここで何が起こっているのか理解できません。エミュレータは24MBのVMに設定されています。その番号はどこですか?私が持っている実際の問題は、エミュレータを16MBに設定した場合、VM Out of Memory例外のある2番目のアクティビティでアプリがクラッシュすることです。 VM 12 MBに設定するか、12 MBの古いHTC Magic電話でVM在庫ですか?また、私のアプリが使いすぎていると思いますか?記憶?これらのDDMS番号が良いかどうかわかりません。

私のコードに関しては、XMLレイアウトで指定されたすべての画像があり、リスナーを追加する以外はプログラムで何もしません。私はここでこのコードを見つけ、私が持っているすべてのアクティビティに追加しました...

@Override
protected void onDestroy() {
    super.onDestroy();

    unbindDrawables(findViewById(R.id.myRootLayout));
    System.gc();
}

private void unbindDrawables(View view) {
    if (view.getBackground() != null) {
        view.getBackground().setCallback(null);
    }
    if (view instanceof ViewGroup && !(view instanceof AdapterView)) {
        for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
            unbindDrawables(((ViewGroup) view).getChildAt(i));
        }
        ((ViewGroup) view).removeAllViews();
    }
}

それ以外の場合は、PNG背景を持つボタンにonClickListenersを追加するだけです。プログラムでボタンの背景を指定する方法を学びたいのですが、ユーザーインタラクションに応じてボタンの背景を変更するには、フォーカス、プレス、フォーカスなし、プレスなどのセレクター機能が必要です。私はこれについてドキュメントをレビューしましたが、それは圧倒的であるため、ヒープの管理の基本からここから始めて、コードでセレクターを指定する方法を検討することにしました。これは意味をなさないかもしれませんが、メモリ不足例外に近づくことなくアプリが割り当てることができる「健全な」量のメモリ割り当てがありますか?たとえば、アプリが6MBを割り当てた場合は問題ありませんが、8MBはそれをプッシュしますが、メモリ割り当てにはそのような境界がありますか?アレックス・ロックウッドの回答に感謝します。この内容が意味をなすまで、もう一度読んで読み直します

30
John P.

エミュレータ/デバイスにVM予算を設定するとき、あなたがしていることは、ヒープに許可される最大サイズを伝えることです。実行時に、Dalvik VMオペレーティングシステムにシステムメモリを要求します。DalvikVMは通常、比較的小さなヒープを割り当てることから始まります。GCが実行されるたびに、空きヒープの合計ヒープに対する比率が小さすぎる場合、Dalvik VMは、ヒープにメモリを追加します(最大構成ヒープサイズまで)。

そうは言っても、DDMS画面に「24 mb」が表示されないのは、ヒープが最大サイズまで成長していないためです。これにより、Android=は、ハンドヘルドデバイスで使用可能な既に少量のメモリを有効に活用できます。

スマートフォンではなくエミュレータでアプリケーションがクラッシュする理由については、奇妙に思えます(数字が正しいことを確認していますか?)。ただし、メモリは動的に管理され、合計メモリ使用率は多くの外部要因(ガベージコレクションが実行される速度/頻度など)に基づいて決定されることに注意してください。

最後に、上記で説明した理由により、上記で提供した1行の情報に基づいて、アプリケーションがメモリをどの程度適切に管理しているかを確実に言うことは困難です。あなたのコードのいくつかを本当に見る必要があります。ただし、OutOfMemoryErrorsは間違いなく心配する価値があるので、アプリケーションのメモリ使用量を間違いなく調べます。考慮すべきことの1つは、inSampleSizeクラスを使用してBitmapFactoryを呼び出して、実行時にビットマップイメージをサンプリングすることです。これにより、描画可能なビットマップをロードするために必要なメモリ量を削減できます。それか、ドローアブルの解像度を下げることができます(ただし、20 kbごとに聞こえますが)。

51
Alex Lockwood

アプリケーションが「24mb」(デバイス内で異なる)ヒープ制限に達していない場合でも、Androidはアプリのヒープスペースを増やすのに時間がかかるため、クラッシュする可能性があります。

私の状況では、短時間で複数の画像を作成してダンプしていました。

かなり頻繁にOutOfMemoryErrorを得ていました。

Androidはアプリのヒープ領域を拡大するのに十分な速さではなかったようです。

マニフェストファイルのlargeHeap設定を使用して、この問題を解決したと思います。この設定をオンにすると、Androidは、ヒープを増やすたびに空きメモリを増やし、現在の制限に達する可能性を最小限に抑えます。

24MBの制限は使用しませんが、このlargeHeap confは非常に便利です。

largeHeap="true"のアプリケーションタグにAndroidManifest.xmlを設定するだけです

<application
    Android:icon="@drawable/ic_launcher"
    Android:label="@string/app_name"
    Android:largeHeap="true"
    Android:theme="@style/AppTheme" >

それでも、@ Alex Lockwoodが勧めたように、画像を扱うときは注意してください。

18
tbraun