android – excepción de falta de memoria al crear bitmap

Recibo el siguiente error después de crear bitmap por segunda vez:

04-17 18:28:09.310: ERROR/AndroidRuntime(3458): java.lang.OutOfMemoryError: bitmap size exceeds VM budget this._profileBitmap = Bitmap.createBitmap(_profileBitmap, xCoor, yCoor, width, height); 

De registro:

 04-17 18:27:57.500: INFO/CameraCropView(3458): Original Photo Size: W 1536 x H 2048 04-17 18:28:06.170: INFO/CameraCropView(3458): xCoor: 291 04-17 18:28:06.170: INFO/CameraCropView(3458): yCoor: 430 04-17 18:28:06.170: INFO/CameraCropView(3458): Width: 952 04-17 18:28:06.170: INFO/CameraCropView(3458): Height: 952 

Como la imagen es enorme, recibo el error. Pero lo interesante es que el error no ocurre la primera vez, solo cuando tomo la fotografía por segunda vez, lo que me hace creer que este perfil BITmap NO se destruye. ¿Cómo limpio esto?

Tuve el mismo problema y lo solucioné de esta manera:

Mi aplicación tenía ~ 18 MB de peso, y cuando veo cuánta memoria quedaba libre, me sorprendió: ¡654 KB (en 1 GB de RAM!). Así que simplemente eliminé casi todas las imágenes del proyecto y las descargué de Internet al primer inicio, y utilicé fotos de la tarjeta SD cuando las necesitaba.

Para verificar la memoria total / libre para el uso de su aplicación:

  Runtime.getRuntime().totalMemory(); Runtime.getRuntime().freeMemory(); 

EDITAR: Olvidé lo principal: agregue su manifiesto, entre tags de actividad, esta línea:

android: largeHeap = “verdadero”

Hay muchos problemas con excepciones de memoria con bitmaps en Android, muchos de los cuales se discuten en stackoverflow. Probablemente sea mejor que revises las preguntas existentes para ver si las tuyas coinciden con una de las existentes, luego, si no, escribe qué hace que tu situación sea diferente.

Algunos ejemplos:

Excepción de falta de memoria debido al tamaño grande del bitmap

Android: excepción de falta de memoria en la Galería

Android maneja la excepción de falta de memoria en el procesamiento de imágenes

etc: https://stackoverflow.com/search?q=android+out+of+memory+exception+bitmap

consejos de procesamiento de bitmap de Android

Ahora aquí hay consejos que puede seguir y puede evitar la excepción de falta de memoria en su aplicación de Android.

  1. Utilice siempre el contexto de la actividad en lugar del contexto de la aplicación. porque el contexto de la aplicación no puede ser basura recolectada. Y libera recursos cuando tu actividad termine. (el ciclo de vida del objeto debe ser el mismo que el de la actividad).

2. Cuando la actividad termina. Compruebe HEAP DUMP (herramienta de análisis de memoria en el estudio de Android).

Si hay objetos en HEAP DUMP de la actividad finalizada, hay pérdida de memoria. revise su código e identifique qué está causando la pérdida de memoria.

  1. Siempre use inSampleSize

Ahora, ¿qué es inSampleSize? con la ayuda de inSampleSize, en realidad le está diciendo al decodificador que no tome cada píxel de la memoria, sino que muestre la imagen de la submuestra. Esto causará que se cargue menos cantidad de píxeles en la memoria que la imagen original. puede decirle al decodificador que capture cada 4º píxel o cada segundo píxel de la imagen original. si inSampleSize es 4. el decodificador devolverá una imagen que es 1/16 del número de píxeles en la imagen original.

Entonces, ¿cuánta memoria has guardado? calcular 🙂

  1. Lea las dimensiones del bitmap antes de cargar en la memoria.

    Cómo leer las dimensiones del bitmap antes de cargar la imagen en la memoria puede ayudarlo a evitar
    error de memoria? Aprendamos

    usar en JustBounds = true

Aquí hay una técnica con la ayuda de la cual puede obtener la dimensión de la imagen antes de cargarla en la memoria

  BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.id.myimage, options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; String imageType = options.outMimeType; 

El fragmento de código anterior no nos dará ninguna imagen / bitmap. devolverá nulo para Objeto de bitmap. pero definitivamente devolverá el ancho y alto de esa imagen. que es R.id.myimage.

Ahora tiene ancho y alto de Imagen. puede ampliar o reducir la imagen según estos factores:

  • Tamaño de ImageView que se usará para mostrar la Imagen.
  • Cantidad disponible de memoria puede verificar la cantidad de memoria disponible usando ActivityManager y getMemoryClass.
  • Tamaño de pantalla y densidad del dispositivo.

    1. Use la configuración de bitmap apropiada

    Las configuraciones de mapas de bits son el espacio de color / profundidad de color de una imagen. La configuración predeterminada del bitmap en Android es RGB_8888, que es de 4 bytes por píxel.

Si usa el canal de color RGB_565 que usa 2 Bytes por píxel. la mitad de la asignación de memoria para la misma resolución 🙂

  1. Use la propiedad inBitmap para fines de reciclaje.

  2. No hagas objetos estáticos extraíbles, ya que no se pueden recolectar basura.

  3. Solicite un montón grande en el archivo de manifiesto.

  4. Utilice procesos múltiples si está haciendo un montón de procesamiento de imágenes (tarea de memoria intensiva) o usa NDK (desarrollo nativo usando c, c ++)

Esto sucede porque está cargando el bitmap directamente, lo que consume mucha memoria. En su lugar, use una versión reducida de la imagen en _profileBitmap. Este chico lo explica bastante bien. http://androidcocktail.blogspot.in/2012/05/solving-bitmap-size-exceeds-vm-budget.html

Podría usar un vector Drawable. Utiliza un archivo xml para describir su imagen, por lo que consume menos memoria. Para hacer eso, debes usar el formato SVG para tus imágenes y luego generar el archivo xml usando una de estas 2 soluciones:

  • Solución 1: utilice el estudio de activos de vectores en Android Studio: haga clic con el botón derecho en el archivo Drawable de su proyecto -> nuevo -> elemento vectorial
  • Solución 2: utilice el sitio web svg2android: https://inloop.github.io/svg2android

Consulte este enlace para obtener más información:
https://developer.android.com/studio/write/vector-asset-studio.html

Puede intentar llamar a recycle () en el bitmap cuando haya terminado con él. Esto borrará todos los datos de la imagen y liberará la memoria. Si algo intenta dibujar el bitmap después de esto, su aplicación se bloqueará. Si consigues un locking, es posible que te ayude a descubrir lo que todavía está reteniendo en tu bitmap.

Tuve este problema porque estaba modificando un bitmap una vez, y luego modificando la versión modificada por segunda vez, lo que resulta en tres versiones del mismo bitmap (original, más las dos versiones modificadas) que están en memoria al mismo tiempo.

Lo arreglé cambiando mi código de edición de imágenes para aplicar ambas modificaciones al mismo bitmap como un tipo de proceso por lotes, reduciendo a la mitad el número de versiones modificadas que mi aplicación tenía que mantener en la memoria.

Tuve el mismo problema cuando el teléfono se apagó y se volvió a encender. Simplemente estableciendo los bitmaps en null y llamando a System.gc (); arregló todos los problemas.

Con imágenes más grandes se puede evitar al muestrearlas en un tamaño más pequeño. Use el siguiente ejemplo:

  File f = new File(selectedImagePath); // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(f), null, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, 720, 1280); //My device pixel resolution // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; Bitmap bmpPic = BitmapFactory.decodeStream(new FileInputStream(f), null, options); Bitmap bmpPic1 = Bitmap.createBitmap(bmpPic, 0, 0, bmpPic.getWidth(), bmpPic.getHeight(), mat, true); img.setImageBitmap(bmpPic1); //img is your ImageView 

Referencia- http://developer.android.com/training/displaying-bitmaps/load-bitmap.html