Buforowanie zdjęć było istotną częścią aplikacji, którą stworzyłem i umieściłem w sklepie z aplikacjami.Aplikacja musi pobierać obrazy i zapisywać je w pamięci podręcznej zarówno w pamięci, jak i na karcie SD, tak aby ich zakres wykraczał poza jednorazowy przebieg.
Ogólna koncepcja polegała na dodaniu obrazów do menedżera buforowania, który zarówno a) przechowuje obraz w pojemniku asocjacyjnym (HashMap), za pomocą klucza na podstawie metadanych, jak i b) zapisuje plik obrazu do pliku SDCard.
W warunkach niskiej ilości pamięci, zwalniam mapę HashMap. Jednak obrazy można nadal pobierać z karty SD_Card i ponownie przechowywać w pamięci podręcznej.
Udało mi się to zrobić bez recyklingu i nadal nie widzę problemów z pamięcią. Jak rozumiem, recykling nie jest konieczny, ale pomaga uzyskać wcześniejsze wydanie pamięci używanej dla "bitmap" z uwagi na to, że przydział dla bitmap, w systemach pre-piernikowych korzysta z Natywnej pamięci. to jest pamięć, która nie jest częścią sterty Dalvik. Tak więc Garbage Collector nie zwalnia tej pamięci, a raczej jest zwalniany przez konkretne zasady implementacji.
To z klasy 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);
}
}
}
// Tutaj przykładem writeImage() z klasy 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;
}
}
30-40 obrazów o wielkości 50x50 nie powinno powodować NIEKTÓRYCH. Być może ładujesz większe? Jeśli tak, możesz je zmniejszyć. Ponadto, jeśli niektóre obrazy zostaną wyczyszczone z SoftReference, nie są używane, więc po prostu je wczytaj ponownie, jeśli to konieczne. –