"Невозможно нарисовать переработанные растровые изображения" при отображении растровых изображений в приложении Галерея, прикрепленных к адаптеру
В Android 4.1 a для меня, похоже, странная ошибка возникает в нашем приложении. В приложении пользовательский адаптер, расширяющий BaseAdapter, присоединяется к виджету "Галерея". При быстрой прокрутке слева направо и наоборот я получаю FC с сообщением об исключении:
java.lang.IllegalArgumentException: Невозможно нарисовать переработанное растровое изображение
Код метода getView (..) выглядит следующим образом:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null){
// View is not recycled. Inflate the layout.
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.gallery_image, parent, false);
viewHolder = new ViewHolder();
viewHolder.image = (ImageView) convertView.findViewById(R.id.gallery_image);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)convertView.getTag();
viewHolder.image.setImageDrawable(null);
}
imageLoader.displayImage(images.get(position).getFilename(),
images.get(position).getUrlThumbnail(),
viewHolder.image,
Math.round(BitmapUtil.convertDpToPixel(400f, context)),
Math.round(BitmapUtil.convertDpToPixel(400f, context)));
return convertView;
}
Я предполагаю, что я должен игнорировать ImageView, но я не могу заставить его работать правильно. ImageLoader - (совершенно) простой класс для загрузки изображений - либо из LruCache, disk/sdcard, либо извлечения его удаленно.
Ответы
Ответ 1
Оказывается, эта ошибка вызвана вызовом oldBitmap.recycle()
в методе entryRemoved(..)
в моем классе, переопределяющем LruCache. Поскольку растровое изображение все еще может быть прикреплено к вызову ImageView recycle()
, это вызовет проблемы.
Если я правильно понимаю: размер кеша LruCache будет установлен в его конструкторе. Когда количество элементов превышает этот размер, объекты будут иметь право на сбор мусора, что произойдет, когда растровое изображение больше не связано с ImageView.
В многочисленных примерах и учебниках по всему миру предлагается recycle()
вызывать в entryRemoved(..)
, но из того, что я вижу, это неправильно.
Ответ 2
Вы получаете эту ошибку, потому что не можете получить доступ к переработанному растровому изображению. Как заявляет сайт разработчика Android:
Освободите собственный объект, связанный с этим растровым изображением, и очистите ссылки на данные пикселя. Это не освободит пиксельные данные синхронно; он просто позволяет собирать мусор, если нет других ссылок. Растровое изображение отмечено как "мертвое", что означает выдает исключение, если вызывается getPixels() или setPixels(), и ничего не рисует. Эта операция не может быть отменена, поэтому она должна вызывается только в том случае, если вы уверены, что для битовая карта. Это расширенный вызов, и его обычно не нужно называть, так как нормальный процесс GC освободит эту память, когда нет больше ссылок на это растровое изображение.
Я предлагаю вам не перерабатывать Bitmap до этого момента, поскольку для него все еще используется. Поэтому перейдите в свой код, когда вы вызываете метод recycle()
, а затем удаляете его.
Когда точка приходит туда, где битмап больше не нужно использовать, я предлагаю вам использовать этот метод для размещения битмапа:
public void disposeBitmap(Bitmap bitmap) {
bitmap.recycle();
bitmap = null;
}
Надеюсь, это поможет.