Будет немного легче понять это, если вы думаете, что приложение, над которым я работаю, как facebook (по крайней мере, это даст вам контекст для того, что я делаю). У меня есть одно действие, которое использует навигатор для обмена фрагментами, каждый из этих фрагментов может иметь от одного до нескольких «субфрагментов». Думайте об этом как о отдельных сообщениях с такими вещами, как textview, несколько кнопок и ImageView. Когда создается «фрагмент контейнера», я вызываю сервер и получаю данные, необходимые для создания всех «фрагментов». Затем я перебираю данные и добавляю все «донные фрагменты» в представление «фрагмент контейнера».Ошибки Android OOM из-за кэширования изображений?
Я заметил, что я использую чрезмерно большой объем памяти (около 129 мб).
Когда создаются подфрагменты, я вызываю эту задачу async, которая извлекает изображения, необходимые каждому фрагменту с сервера, и помещает их в свой ImageView.
public class URLImageFactory extends AsyncTask<String, Void, Bitmap>
{
ImageView imgView;
private static final ImgCache mCache = new ImgCache();
public URLImageFactory(ImageView bmImage) {
this.imgView = bmImage;
}
@Override
protected Bitmap doInBackground(String... urls) {
String urldisplay = Config.SERVER_URL + urls[0].replaceAll("\\s+","%20");
Bitmap bitmap = null;
//If it is in the cache don't bother pulling it from the server
if(bitmap != null)
{
return bitmap;
}
try {
InputStream in = new java.net.URL(urldisplay).openStream();
//This is in case we are using match_parent/wrap content
if(imgView.getWidth() == 0 || imgView.getHeight() == 0)
{
bitmap = BitmapFactory.decodeStream(in);
} else {
bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(in),
imgView.getWidth(), imgView.getHeight(), false);
}
mCache.put(urldisplay,bitmap);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
imgView.setImageBitmap(result);
}
}
Я сделал элементарную попытку кэширования изображений ускорить процесс
общественного класса ImgCache расширяет LruCache {
public ImgCache() {
super(calculateCacheSize());
}
public static int calculateCacheSize()
{
int maxMemory = (int) Runtime.getRuntime().maxMemory()/8;
int cacheSize = maxMemory;
return cacheSize;
}
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount()/1024;
}
}
Мое приложение рушится с OutOfMemory исключением. Я также заметил, что когда мой «фрагмент контейнера» заменяется на другой ... обычно аналогично структурированный фрагмент ... onPause() и onStop() этих подфрагментов не запускаются. Если это помогает, то субфрагменты являются статическими внутренними классами, а фрагмент контейнера - нет. Я думаю, что это проблема, связанная с растровым изображением, но я не уверен. Я попытался использовать TransactionManager.remove (фрагмент) во всех дочерних фрагментах, когда родительский элемент попадает в onPause, но он, похоже, не помогает.
Вы пытались использовать анализатор памяти eclipse, чтобы узнать, какие объекты занимают память в вашем приложении? Кроме того, нужно указать «Runtime.getRuntime(). MaxMemory()' сообщает вам количество байтов. Почему вы разделите его на 8? –
Я разделил его на 8, потому что я понял, что 1/8-я память была подходящей для кеша ... было больше угадывания – ed209
Я не мог не заметить, что каждый раз, когда он добавляет растровое изображение в пользовательский интерфейс, он выплевывается. Grow heap (фрагмент case) до #### – ed209