6

私のアプリケーションでは、シンプルなギャラリーとカバーフローの両方を使用しています。カバーフローでクリックされた画像にカバーフロー画像ギャラリーがあります。コンテンツがフルスクリーンギャラリーである次のアクティビティにリダイレクトされ、フルスクリーンギャラリーをスクロールすることもできます。しかし、アプリに大量の画像や高解像度の画像を入れると、ビットマップのサイズがVMの予算を超えているために強制的に閉じられます

だから私はカバーフローとギャラリーを終了するたびにヒープメモリをクリアしたいので、アプリに任意の量または任意の解像度の画像をロードできるので、誰かが私を助けることができれば...毎回ヒープメモリをクリア/空にする方法コードでアクティビティを動的に終了しますか?私はすでにリサイクルとSystem.gcメソッドを試しました

4

1 に答える 1

31

「ヒープをクリア」することはできません。オブジェクトが参照されなくなると、VMは自動的にそれを行います。

そうは言っても、Androidではビットマップは難しいものです。メモリには限りがあり、画像がビットマップにデコードされると、圧縮された画像形式自体よりもはるかに多くのメモリを消費する可能性があります。

あなたの解決策に対する簡単な答えはありません。すべてを正しく行ったとしても、単にメモリが不足している可能性があります。そうは言っても、ここにいくつかのヒントがあります:

  1. を使用しBitmap.release()ます。ビットマップは、(VMではなく)ネイティブスタックに割り当てられるという点で特別です。javadocsは少しあいまいで、通常はこれを呼び出す必要はないと言っていますが、私の経験では、ビットマップをバックアップするメモリで完了したというVMへのこの「手がかり」が重要です。編集:Android 3.0(APIレベル11)以降、ピクセルデータは関連するビットマップとともにDalvikヒープに保存されます。

  2. ビットマップをメモリスケーリングされたものにロードします。これがこのトピックに関するブログ投稿です。一部のデバイスでは24MBのヒープしか得られず、高解像度の画像をビットマップオブジェクトにロードすると、そのすべてが使い果たされる可能性があります。それを回避する方法はないので、スケーリングしてロードする必要があります。

  3. System.gc()別の答えが言ったように電話しないでください。GCアルゴリズムを構築した人々は、あなたや私よりも賢いです。彼らは自分たちが何をしているのかを知っています。GCを介して解放できるメモリがある場合、OOMEを取得することはありません。GCは常にOOMEを提供する前に実行されます。

  4. これは明らかですが、ビットマップが不要になったときに、ビットマップへの参照を保持していないことを確認してください。

  5. 最後に、これは残念ですが、Androidはヒープ圧縮を行いません。これが私が少し前に投稿したSOの質問ですが、満足のいく答えはありません。一言で言えば、Androidはヒープを圧縮しないため、アプリがビットマップに大きなチャンクまたは中サイズのチャンクを割り当て続けると、最終的には、メモリが不足していないのに、十分な大きさの連続したものがない状況になります。割り当て用のメモリのチャンクで、OOMEを取得します。私が質問で書いたように、これを回避する唯一の方法は、ユーザーが終了したときにアプリのプロセスを強制終了することです。これにより、次回の起動が遅くなりますが、新しいヒープが保証されます。誤解しないでください。これが正しいことだとは信じられませんが、より良い解決策を思いついた人は誰もいません。

于 2012-03-21T05:30:25.363 に答える