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 .
Timmmm tenía razón.
de acuerdo con: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
Además, antes de Android 3.0 (API nivel 11), los datos de respaldo de un mapa de bits se almacenaron en la memoria nativa, que no se publica de manera predecible, lo que puede causar que una aplicación exceda brevemente sus límites de memoria y falle.
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.