El almacenamiento en caché de imágenes fue una parte importante de una aplicación que he creado y puesto en la tienda de aplicaciones.La aplicación necesita descargar imágenes y almacenarlas en caché, tanto en la memoria como en la tarjeta SD, para que su alcance se extienda más allá de una sola ejecución.
La idea general fue agregar las imágenes a un Caching Manager que a) almacena la imagen en un contenedor asociativo (HashMap), a través de una clave basada en los metadatos, yb) escribe el archivo de imagen en el Tarjeta SD.
Durante condiciones de poca memoria, libero el HashMap. Sin embargo, las imágenes se pueden recuperar de la tarjeta SD_Card y una vez más la memoria caché.
Pude hacer esto sin reciclar y todavía no veo problemas de memoria. Según entiendo, el reciclaje no es necesario, pero ayuda a obtener una versión anterior de la memoria utilizada para "mapas de bits" debido al hecho de que la asignación para mapas de bits, en sistemas operativos anteriores a Gingerbread, usa memoria nativa. es decir, memoria que no es parte del montón de Dalvik. Entonces, el recolector de basura no libera esta memoria, sino que es liberada por políticas específicas de implementación.
Esto es de la clase Cache_Manager:
public static synchronized void addImage(Bitmap b, String urlString, boolean bSaveToFile, IMAGE_TYPES eIT, boolean bForce)
{
String szKey = getKeyFromUrlString(urlString, eIT);
if (false == m_hmCachedImages.containsKey(szKey) || bForce)
{
m_hmCachedImages.put(szKey, b);
if (bSaveToFile)
{
boolean bIsNull = false;
// Write a null object to disk to prevent future query for non-existent image.
if (null == b)
{
try
{
bIsNull = true;
b = getNullArt();
}
catch (NullPointerException e)
{
e.printStackTrace();
throw e;
}
}
// Don't force null art to disk
if (false == File_Manager.imageExists(szKey) || (bForce && bIsNull == false))
File_Manager.writeImage(b, szKey);
}
}
}
// Aquí un ejemplo de writeImage() de la clase File_Manager
public static void writeImage(Bitmap bmp, String szFileName)
{
checkStorage();
if (false == mExternalStorageWriteable)
{
Log.e("FileMan", "No Writable External Device Available");
return;
}
try
{
// Create dirctory if doesn't exist
String szFilePath = getFilesPath();
boolean exists = (new File(szFilePath)).exists();
if (!exists)
{
new File(szFilePath).mkdirs();
}
// Create file
File file = new File(szFilePath, szFileName);
// Write to file
FileOutputStream os = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, os);
} catch (IOException e)
{
// Unable to create file, likely because
// external storage is
// not currently mounted.
Log.e("FileMan", "Error writing file", e);
} catch (Exception e)
{
e.printStackTrace();
throw e;
}
}
Las imágenes de 30-40 del tamaño 50x50 no deben causar OOME. ¿Quizás cargue las más grandes? Si es así, puedes escalarlos. Además, si algunas imágenes se limpian de SoftReference, no se están utilizando, así que simplemente vuelva a cargarlas si es necesario. –