Androidのメモリオーバーフロー(Out Of Memory)のまとめ
画像が増え、メモリオーバーフローが注意せざるを得ない問題になっています.
エラーログ:11-03 12:36:54.82:ERROR/Android Runtime(5084):Caused by:java.lang.OutOfMemoryError: bitmap size exceeds VM budget
メモリオーバーフローは、主に次のような状況で発生します.
1.データベースのcursorが閉じていません.
2.構築adapterはキャッシュconvertviewを使用していません.
3.registerReceiverが呼び出された後、unregisterReceiver()は呼び出されませんでした.
4.InputStream/OutputStreamをオフにしていません.
5.Bitmap使用後にrecycle()は呼び出されませんでした.
6.Context漏洩.
最初の5つの状況は発見しやすく、解決しやすく、この関門をタイムリーに閉じ、この呼び出しの方法をタイムリーに呼び出すだけで、あまり問題はありません.またjavaにはソフトリファレンスがメモリの管理を助けています.
SoftReference bitmap; bitmap = new SoftReference(pBitmap); if(bitmap != null){
if(bitmap.get() != null && !bitmap.get().isRecycled()){ bitmap.get().recycle(); bitmap = null; } }
Contextリークについて重点的に説明します.
これは暗いメモリの漏洩です.まずAndroidの公式サイトで提供されている例を見てみましょう.
このコードは効率が速いが、同時に極めて間違っている.最初の画面方向切り替え時に作成したActivityが漏れました.1つのDrawableが1つのViewにアタッチされると、ViewはそれをcallbackとしてDrawableに設定します.上記のコードフラグメントは、DrawableがTextViewの参照を持ち、TextViewがActivity(Contextタイプ)の参照を持つことを意味し、言い換えればDrawableがより多くのオブジェクト参照を持つことを意味する.Activityが破棄されてもメモリは解放されません.
また、Contextへの参照がそれ自体のライフサイクルを超えると、Contextが漏洩することもあります.なるべくApplicationというContextタイプを使います.このContextは、アプリケーションと同様に長いライフサイクルを持ち、Activityのライフサイクルに依存しません.長い間オブジェクトを保存し、Contextが必要な場合は、Applicationオブジェクトを使用してください.Contextを呼び出すことができますgetApplicationContext()またはActivity.getApplication()は、Applicationオブジェクトを簡単に入手できます.
最近Contextの漏洩が発生したのは、Activityが破棄されたときに、他のスレッドが停止していないことです.
Contextの漏洩を避けるために注意すべき問題をまとめます.
1.アプリケーションというContextタイプを使用します.
2.Contextへの参照は、それ自体のライフサイクルを超えないように注意してください.
3.「static」キーワードを慎重に使う.
4.Contextにスレッドがある場合は、必ずonDestroy()でタイムリーに停止してください.
エラーログ:11-03 12:36:54.82:ERROR/Android Runtime(5084):Caused by:java.lang.OutOfMemoryError: bitmap size exceeds VM budget
メモリオーバーフローは、主に次のような状況で発生します.
1.データベースのcursorが閉じていません.
2.構築adapterはキャッシュconvertviewを使用していません.
3.registerReceiverが呼び出された後、unregisterReceiver()は呼び出されませんでした.
4.InputStream/OutputStreamをオフにしていません.
5.Bitmap使用後にrecycle()は呼び出されませんでした.
6.Context漏洩.
最初の5つの状況は発見しやすく、解決しやすく、この関門をタイムリーに閉じ、この呼び出しの方法をタイムリーに呼び出すだけで、あまり問題はありません.またjavaにはソフトリファレンスがメモリの管理を助けています.
SoftReference
if(bitmap.get() != null && !bitmap.get().isRecycled()){ bitmap.get().recycle(); bitmap = null; } }
Contextリークについて重点的に説明します.
これは暗いメモリの漏洩です.まずAndroidの公式サイトで提供されている例を見てみましょう.
private static Drawable sBackground;
@Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
if (sBackground == null) {
sBackground = getDrawable(R.drawable.large_bitmap);
}
label.setBackgroundDrawable(sBackground);
setContentView(label);
}
このコードは効率が速いが、同時に極めて間違っている.最初の画面方向切り替え時に作成したActivityが漏れました.1つのDrawableが1つのViewにアタッチされると、ViewはそれをcallbackとしてDrawableに設定します.上記のコードフラグメントは、DrawableがTextViewの参照を持ち、TextViewがActivity(Contextタイプ)の参照を持つことを意味し、言い換えればDrawableがより多くのオブジェクト参照を持つことを意味する.Activityが破棄されてもメモリは解放されません.
また、Contextへの参照がそれ自体のライフサイクルを超えると、Contextが漏洩することもあります.なるべくApplicationというContextタイプを使います.このContextは、アプリケーションと同様に長いライフサイクルを持ち、Activityのライフサイクルに依存しません.長い間オブジェクトを保存し、Contextが必要な場合は、Applicationオブジェクトを使用してください.Contextを呼び出すことができますgetApplicationContext()またはActivity.getApplication()は、Applicationオブジェクトを簡単に入手できます.
最近Contextの漏洩が発生したのは、Activityが破棄されたときに、他のスレッドが停止していないことです.
Contextの漏洩を避けるために注意すべき問題をまとめます.
1.アプリケーションというContextタイプを使用します.
2.Contextへの参照は、それ自体のライフサイクルを超えないように注意してください.
3.「static」キーワードを慎重に使う.
4.Contextにスレッドがある場合は、必ずonDestroy()でタイムリーに停止してください.