Recycle ImageView Bitmap

У меня есть что-то вроде этого:

Bitmap.Config conf = Bitmap.Config.ARGB_8888;
WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, conf));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView.setImageBitmap(bm);

И я применяю это на более чем 10 imageView, которые создаются один за другим. Всякий раз, когда я создаю новый ImageView, я хочу перерабатывать объект "bm" из первого, вызывать этот код там, заставляет кучу расти все больше и больше, а затем бросать OutOfMemoryError, поэтому я делаю:

bm.recycle()

сразу после того, как я установил Bitmap (bm) в объект imageView. Это вызывает исключение, что холст ImageView хочет нарисовать переработанную растровую карту.

Каким образом можно переработать Bitmap, который уже был помещен как изображение в ImageView?

Thanksb

Ответ 1

В вашем методе onDestroy вы можете попробовать что-то вроде этого:

ImageView imageView = (ImageView)findViewById(R.id.my_image);
Drawable drawable = imageView.getDrawable();
if (drawable instanceof BitmapDrawable) {
    BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
    Bitmap bitmap = bitmapDrawable.getBitmap();
    bitmap.recycle();
}

Приведение должно работать, поскольку setImageBitmap реализован как

public void setImageBitmap(Bitmap bm) {
    setImageDrawable(new BitmapDrawable(mContext.getResources(), bm));
}

Ответ 2

Если вы установите один и тот же объект растрового изображения на всех своих ImageView s, он не должен бросать OutOfMemoryError. В принципе, это должно работать:

WeakReference<Bitmap> bm = new WeakReference<Bitmap>(Bitmap.createBitmap(3000 + 3000, 2000, Bitmap.Config.ARGB_8888));

Canvas canvas = new Canvas(bm.get());
canvas.drawBitmap(firstBitmap, 0, 0, null);
canvas.drawBitmap(bm, firstBitmap.getWidth(), 0, null);

imageView1.setImageBitmap(bm.get());
imageView2.setImageBitmap(bm.get());
imageView3.setImageBitmap(bm.get());
imageView4.setImageBitmap(bm.get());
imageView5.setImageBitmap(bm.get());
// ...

Если это не работает, это просто означает, что ваше растровое изображение слишком велико (6000x2000 пикселей составляет около 12 мегабайт, если я правильно рассчитал). Вы можете:

  • сделать растровое изображение меньше
  • сократить другие вещи, которые используют много памяти

Ответ 3

Ответ на Devconsole велик, но вы также можете хранить все объекты растровых изображений в списке как член вашего класса, а затем перерабатывать их в цикле, когда метод активности onDestroy() (или какой-либо другой метод жизненного цикла релиза компонента, в котором вы используете bitmap).

Ответ 4

Не создавайте изображения больше, чем вам нужно в любой момент времени. Ограничения кучи предназначены для того, чтобы вы не повесились и полностью захватили ограниченную память устройства.

Если вам нужно больше деталей, потому что вы планируете увеличивать масштаб, тогда повторно отрисуйте эту часть изображения с более высокой детализацией во время масштабирования, исключая части, которые вы не просматриваете.