30

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

これは私が何が起こっているのか理解できないところです、私のエミュレーターは24MBのVMに設定されています。その番号はどこにありますか?私が抱えている実際の問題は、エミュレーターを16MBのVMに設定すると、2番目のアクティビティでアプリがクラッシュし、メモリ不足の例外が発生することです。VMが12MBに設定されている電話、または12MBのVMストックがある古いHTCMagic電話でクラッシュしないのはなぜですか?また、私のアプリはメモリを使いすぎていませんか?それらの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();
    }
}

onClickListenersそれ以外の場合は、PNGの背景を持つボタンに追加するだけです。プログラムでボタンの背景を指定する方法を学びたいのですが、ユーザーの操作に応じてボタンの背景を変更するには、フォーカス、プレス、フォーカスなし、プレスなどのセレクター機能が必要です。これに関するドキュメントを確認しましたが、圧倒されるようです。そのため、ここからヒープの管理の基本から始めて、コードでセレクターを指定するまでの道を進んでいくと思いました。これは意味がないかもしれませんが、メモリ不足の例外に近づくことなくアプリが割り当てることができる「正常な」量のメモリ割り当てはありますか?たとえば、アプリが6MBを割り当てた場合、それは問題ないはずですが、8MBがそれをプッシュしますが、メモリ割り当てにそのような境界はありますか?

4

2 に答える 2

51

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

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

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

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

于 2012-05-21T03:22:10.013 に答える
19

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

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

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

Androidは、私のアプリのヒープスペースを増やすのに十分な速度ではなかったようです。

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

私は24MBの制限を使用しませんが、このlargeHeapconfは非常に便利でした。

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

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

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

于 2013-01-22T15:25:55.163 に答える