Я разрабатываю приложение с очень интенсивной обработкой изображений, где у меня есть несколько ListFragments
по горизонтали FragmentStatePagerAdapter
. Я настойчиво использую практически все приемы и предложения, которые мне удалось найти здесь и в других местах. Я загружаю растровые изображения и сохраняю их на SD-карту, а также в виде кэш-памяти памяти.
Тем не менее, когда я использую приложение в определенный момент, я начинаю видеть сообщения в LogCat, как показано ниже
11-05 15:57:43.951: I/dalvikvm-heap(5449): Clamp target GC heap from 32.655MB to 32.000MB
11-05 15:57:43.951: D/dalvikvm(5449): GC_FOR_MALLOC freed 0K, 24% free 11512K/14983K, external 17446K/17896K, paused 64ms
11-05 15:57:44.041: D/dalvikvm(5449): GC_EXTERNAL_ALLOC freed <1K, 24% free 11511K/14983K, external 17258K/17896K, paused 77ms
Если я продолжу, сообщения выше станут более срочными
11-05 16:02:09.590: D/dalvikvm(5449): GC_FOR_MALLOC freed 0K, 23% free 11872K/15239K, external 17497K/17896K, paused 71ms
11-05 16:02:09.700: D/dalvikvm(5449): GC_EXTERNAL_ALLOC freed <1K, 23% free 11872K/15239K, external 17497K/17896K, paused 84ms
11-05 16:02:09.720: E/dalvikvm-heap(5449): 192816-byte external allocation too large for this process.
11-05 16:02:09.800: I/dalvikvm-heap(5449): Clamp target GC heap from 33.057MB to 32.000MB
11-05 16:02:09.800: D/dalvikvm(5449): GC_FOR_MALLOC freed 0K, 23% free 11872K/15239K, external 17497K/17896K, paused 68ms
11-05 16:02:09.800: E/GraphicsJNI(5449): VM won't let us allocate 192816 bytes
И приложение неизбежно завершится с OutOfMemoryException
Симптомами являются классическая утечка памяти. Тем не менее, в моем методе Fragment#onDestroy
я отменяю все отложенные задачи, отменяю привязку и аннулирую представления и вызываю Bitmap # recycle.
Интересно, что я вижу вызовы GC в LogCat, но даже если я задерживаюсь на длительный период, память никогда не освобождается.
У меня такое ощущение, что постоянное перечитывание изображений с SD вызывает деградацию и неизбежный упадок
Вот метод очистки служебной программы, который я использую, пытаясь стряхнуть отрисовки (как я уже сказал, для отмены отложенных / запущенных задач и пустых адаптеров ListView)
public static void unbindDrawables(View view, final boolean agressive) {
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i), agressive);
}
if (!AdapterView.class.isInstance(view)) {
((ViewGroup) view).removeAllViews();
}
} else {
Drawable bmp = view.getBackground();
if (bmp == null && ImageView.class.isInstance(view)) bmp = ((ImageView) view).getDrawable();
if (bmp != null) {
bmp.setCallback(null);
if (agressive && (TaggedDrawable.class.isInstance(bmp))) {
Bitmap bm = ((BitmapDrawable) bmp).getBitmap();
if (bm != null) {
if (DEBUG) Log.i(TAG, "Forcing bitmap recycle for " + bmp);
bm.recycle();
bm = null;
view.destroyDrawingCache();
view = null;
}
}
}
}
}
Излишне говорить, что я серьезно обеспокоен этим моментом и буду очень признателен за любые предложения