outofmemoryerror oom error android bitmap

oom - Android: ¿Cómo funciona Bitmap recycle()?



outofmemoryerror android bitmap (5)

Digamos que he cargado una imagen en un objeto de mapa de bits como

Bitmap myBitmap = BitmapFactory.decodeFile(myFile);

Ahora, ¿qué pasará si cargo otro mapa de bits como

myBitmap = BitmapFactory.decodeFile(myFile2);

¿Qué pasa con el primer myBitmap? ¿Obtiene Garbage Collected o tengo que recolectarlo manualmente antes de cargar otro mapa de bits, por ej. myBitmap.recycle() ?

Además, ¿hay una mejor manera de cargar imágenes grandes y mostrarlas una tras otra mientras se recicla en el camino?


Creo que el problema es el siguiente: en las versiones anteriores a Honeycomb de Android, los datos de mapa de bits en bruto no se almacenan en la memoria de la máquina virtual, sino en la memoria nativa. Esta memoria nativa se libera cuando el objeto de Bitmap java correspondiente es GC''d.

Sin embargo , cuando te quedas sin memoria nativa, el dalvik GC no se activa, por lo que es posible que tu aplicación utilice muy poca memoria java, por lo que el dalvik GC nunca se invoca, aunque utiliza toneladas de memoria nativa para mapas de bits. que eventualmente causa un error OOM.

Al menos esa es mi suposición. Afortunadamente en Honeycomb y más tarde, todos los datos de mapas de bits se almacenan en la máquina virtual, por lo que no debería tener que usar recycle() en absoluto. Pero para los millones de usuarios de 2.3 (la fragmentación sacude el puño ), debe usar recycle() siempre que sea posible (una molestia masiva). O, como alternativa, puede invocar el GC en su lugar.


Deberá llamar a myBitmap.recycle () antes de cargar la siguiente imagen.

Dependiendo de la fuente de su myFile (por ejemplo, si no tiene control sobre el tamaño original), al cargar una imagen en lugar de simplemente volver a muestrear un número arbitrario, debe escalar la imagen al tamaño de visualización.

if (myBitmap != null) { myBitmap.recycle(); myBitmap = null; } Bitmap original = BitmapFactory.decodeFile(myFile); myBitmap = Bitmap.createScaledBitmap(original, displayWidth, displayHeight, true); if (original != myBitmap) original.recycle(); original = null;

Guardo en caché el displayWidth y displayHeight en una estática que inicié al inicio de mi actividad.

Display display = getWindowManager().getDefaultDisplay(); displayWidth = display.getWidth(); displayHeight = display.getHeight();


El primer mapa de bits no recibe GC cuando decodifica el segundo. GC lo hará más tarde cuando lo decida. Si desea liberar memoria lo antes posible, debe llamar a reciclar () justo antes de decodificar el segundo mapa de bits.

Si desea cargar una imagen realmente grande, debe volver a muestrearla. Aquí hay un ejemplo Extraño problema de memoria al cargar una imagen en un objeto Bitmap .



Una vez que el mapa de bits había sido cargado en la memoria, de hecho fue hecho por dos partes de datos. La primera parte incluye información sobre el mapa de bits, otra parte incluye información sobre los píxeles del mapa de bits (está ordenada por una matriz de bytes). La primera parte existe en la memoria utilizada de Java, la segunda parte exisita en la memoria utilizada de C ++. Puede usar la memoria de los demás directamente. Bitmap.recycle () se usa para liberar la memoria de C ++. Si solo hace eso, el GC recogerá la parte de java y siempre se usará la memoria de C.