Я использую LRUCache
для кешировать растровые изображения, которые хранятся в файловой системе. Я построил кеш на основе приведенных здесь примеров: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html
Проблема в том, что я наблюдаю частые сбои OutOfMemory при использовании приложения. Я считаю, что когда LRUCache вытесняет образ, чтобы освободить место для другого, память не освобождается.
Я добавил вызов Bitmap.recycle() при удалении изображения:
// use 1/8 of the available memory for this memory cache
final int cacheSize = 1024 * 1024 * memClass / 8;
mImageCache = new LruCache(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount();
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
oldBitmap.recycle();
oldBitmap = null;
}
};
Это устраняет сбои, однако также приводит к тому, что изображения иногдане отображаются в приложении (просто черное пространство где должно быть изображение). Каждый раз, когда это происходит, я вижу это сообщение в своем Logcat: Невозможно сгенерировать текстуру из растрового изображения
.
Быстрый поиск в Google показывает, что это происходит потому, что отображаемое изображение было переработано.
Так что же здесь происходит? Почему переработанные изображения все еще находятся в LRUCache, если я перерабатываю их только после того, как они были удалены? Какова альтернатива реализации кеша? В документации по Android четко указано, что LRUCache — это то, что нужно, но в них не упоминается необходимость перерабатывать растровые изображения или как это сделать.
РЕШЕНО:
В случае, если это полезно для кого-либо еще, решение этой проблемы, предложенное принятым ответом, состоит в том, чтобы НЕ делать то, что я сделал в приведенном выше примере кода (не перерабатывать растровые изображения в entryRemoved ()
вызов).
Вместо этого, когда вы закончите работу с ImageView (например, onPause()
в действии или когда представление повторно используется в адаптере), проверьте, находится ли растровое изображение в кеше (I добавил метод isImageInCache()
к моему классу кеша) и, если это не так, то переработать растровое изображение. В противном случае оставьте его в покое.Это исправило мои исключения OutOfMemory
и предотвратило повторное использование растровых изображений, которые все еще использовались.