Android: Fuera de error de memoria

Cuando minimizo mi aplicación de Android por 4 o 5 veces, siempre obtengo el siguiente error:

02-01 19:24:11.980: E/dalvikvm-heap(22362): Out of memory on a 3686416-byte allocation. 02-01 19:24:12.000: E/dalvikvm(22362): Out of memory: Heap Size=62755KB, Allocated=55237KB, Limit=65536KB 02-01 19:24:12.000: E/dalvikvm(22362): Extra info: Footprint=62435KB, Allowed Footprint=62755KB, Trimmed=2144KB 02-01 19:24:12.000: E/Bitmap_JNI(22362): Create Bitmap Failed. 02-01 19:24:12.000: E/Bitmap_JNI(22362): Failed to create SkBitmap! 02-01 19:24:12.000: E/AndroidRuntime(22362): FATAL EXCEPTION: main 02-01 19:24:12.000: E/AndroidRuntime(22362): java.lang.OutOfMemoryError: (Heap Size=62755KB, Allocated=55237KB) 02-01 19:24:12.000: E/AndroidRuntime(22362): at android.graphics.Bitmap.nativeCreateScaledBitmap(Native Method) 02-01 19:24:12.000: E/AndroidRuntime(22362): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:744) 02-01 19:24:12.000: E/AndroidRuntime(22362): at de.vauge.mb.Utils.getResizedBitmap(Utils.java:56) 02-01 19:24:12.000: E/AndroidRuntime(22362): at de.vauge.mb.MenuView.initialize(MenuView.java:74) 02-01 19:24:12.000: E/AndroidRuntime(22362): at de.vauge.mb.MenuView$1.handleMessage(MenuView.java:137) 02-01 19:24:12.000: E/AndroidRuntime(22362): at android.os.Handler.dispatchMessage(Handler.java:99) 02-01 19:24:12.000: E/AndroidRuntime(22362): at android.os.Looper.loop(Looper.java:156) 02-01 19:24:12.000: E/AndroidRuntime(22362): at android.app.ActivityThread.main(ActivityThread.java:5045) 02-01 19:24:12.000: E/AndroidRuntime(22362): at java.lang.reflect.Method.invokeNative(Native Method) 02-01 19:24:12.000: E/AndroidRuntime(22362): at java.lang.reflect.Method.invoke(Method.java:511) 02-01 19:24:12.000: E/AndroidRuntime(22362): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 02-01 19:24:12.000: E/AndroidRuntime(22362): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 02-01 19:24:12.000: E/AndroidRuntime(22362): at dalvik.system.NativeStart.main(Native Method) 

Mi aplicación se compone de una sola actividad que tiene 7 vistas diferentes, auto-escritas (todos ellos contienen algunos mapas de bits) en ellos, y se cambian invisibles cuando no se necesitan (Probablemente no es un buen estilo, pero funcionó para mí hasta ahora …). Cada una de esas vistas tiene una función destroy () que recicla todos los mapas de bits que se utilizan en él, y el onDestroy () de MainActivity llama a todas las funciones destroy (). Además, no utilicé ningún Bitmaps estático.

Por lo tanto, ¿hay algo más que podría probar, además de reciclar todos los mapas de bits y no utilizar estática Bitmaps?

Bien. Bitmaps en Android puede ser un poco complicado. ¿Puede dar una mejor información sobre las fuentes de los mapas de bits y sus tamaños?

De lo contrario, te recomiendo mirar en estas cosas:

  1. Si está cargando imágenes remotas, consulte fresco . También puede visitar Picasso . Yo personalmente me gustaba ImageLoader , pero ya no se mantiene.

  2. Si está utilizando el indicador inPurgable que solía ser una opción recomendada, intente encontrar una forma de evitarlo, ya que en realidad provoca que se asignen más memoria para cada imagen.

  3. Si usted decodifica pequeños activos locales frecuentemente, considere guardar sus elementos desplegables en un hashmap y reutilizarlos cuando sea necesario. Menos GC.

  4. Si te interesa subclasificar tu Aplicación, puedes usar la llamada de OnLowMemory para saber cuando probablemente necesitas limpiar (sobre todo buena para depurar, no situaciones de la vida real) … Si eso no es demasiado tarde … 🙂

  5. Eche un vistazo al blog de Chris Banes. Esta es una solución bastante interesante memoria caché

  6. Implemente un recortador de memoria que llame siempre que sea necesario y posible.

  7. Una otra optimización unsurprising es utilizar objetos más pequeños cuando usted puede … Piense en sus modelos mínimos de los datos y tamaños de la imagen y trate de tener un API que se adapte a ésos.

Para # 3 de Ben Max comento hice dos clases útiles:

 public abstract class SoftReferenceStorage<K, V>{ private static HashMap<Object, SoftReference<Object>> objectsHash = new HashMap<Object, SoftReference<Object>>(); @SuppressWarnings("unchecked") public V get(K key) { if (objectsHash.containsKey(key)) { SoftReference<Object> ref = objectsHash.get(key); if (ref.get() == null) { objectsHash.put(key, new SoftReference<Object>(createValueForKey(key))); return (V)objectsHash.get(key).get(); } else { return (V)ref.get(); } } else { objectsHash.put(key, new SoftReference<Object>(createValueForKey(key))); return (V)objectsHash.get(key).get(); } } protected abstract V createValueForKey(K key); } 

y

 public class FrequentlyUsedBitmapResources extends SoftReferenceStorage<Integer, Bitmap>{ private static FrequentlyUsedBitmapResources instance = null; private Resources resources; public FrequentlyUsedBitmapResources(Resources resources) { super(); this.resources = resources; } public static FrequentlyUsedBitmapResources getInstance() { if (instance == null) { instance = new FrequentlyUsedBitmapResources(HiDriveApp.getContext().getResources()); } return instance; } @Override protected Bitmap createValueForKey(Integer resId) { return BitmapFactory.decodeResource(resources, resId); } } 

Se puede utilizar como:

 Bitmap b = FrequentlyUsedBitmapResources.getInstance().get(R.drawable.overview_photo_placeholder); 

Asegúrese de que los está cargando en onCreate() y no en onStart() o onResume() . Parece que se están recargando cada vez que se reanuda, pero no se destruyen porque onDestroy() no se llama cuando se minimiza la aplicación.

Si las imágenes están en el dispositivo local (es decir, ya sea incorporado con su código o vienen de la biblioteca de imágenes de usuario), entonces puedo elegir no tenerlos simplemente ir invisible o no, sino simplemente traerlos sobre la marcha desde el disco. Como resulta, todos estos dispositivos son esencialmente basado en flash que es extremadamente rápido en comparación con los discos de husillo. Lo más probable, el usuario no será capaz de sentir el éxito de rendimiento de IO de disco para las imágenes.

De esta manera también, se limita el AMOUNT de imágenes que están reteniendo en la memoria en cualquier momento.

Estoy de acuerdo en que usted debe mirar en la evaluación de Tim también.

  • Heap sigue aumentando en Google Map API V2
  • Android montón 1-tipo de matriz de bytes extremadamente grande
  • Los archivos masivos de hprof que se crean de alguna manera, me impide empujar
  • Android: BitmapFactory.decodeStream () sin memoria con un archivo de 400 KB con 2 MB de montón libre
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.