Я создаю приложение для просмотра, которое вызывает BitmapRegionDecoder.decodeRegion(Rect, BitmapFactory.Options)
. Я избавляюсь от растрового изображения, полученного ранее от decodeRegion
перед каждым вызовом:
//this is a function I wrote that gets the rectangle I need
//from the zoom/pan state of a lower-resolution ImageView (page).
//it is bragable.
Rect areaRect = page.getBitmapRegionDecoderRect(areaBitmapRect);
BitmapFactory.Options options = new BitmapFactory.Options();
//area is the ImageView which will get the hi-res bitmap in it.
if(area.getHeight()!=0)
{
//I used Math.round because we are so desperate to save memory!
//The consequent blurring is actually not too bad.
options.inSampleSize = Math.round( ((float) areaRect.height()) / ((float) area.getHeight()) );
}
else
{
options.inSampleSize = Math.round( ((float) areaRect.height()) / ((float) page.getHeight()) );
}
if(options.inSampleSize==0) options.inSampleSize=1;
if(options.inSampleSize>16) options.inSampleSize=16;
options.inPreferredConfig = Bitmap.Config.RGB_565;
if(areaRect.left<0) areaRect.left = 0;
if(areaRect.right>areaBitmapRect.right) areaRect.right = areaBitmapRect.right;
if(areaRect.top<0) areaRect.top = 0;
if(areaRect.bottom>areaBitmapRect.bottom) areaRect.bottom = areaBitmapRect.bottom;
if(areaBitmap!=null)
{
//recycling our garbage ... or are we?
areaBitmap.recycle();
areaBitmap = null;
try
{
//dirty hack
wait(200);
}
catch(Exception x)
{
//something happened.
}
}
//the all-important call
areaBitmap = areaDecoder.decodeRegion(areaRect, options);
area.setImageBitmap(areaBitmap);
У меня были проблемы с тем фактом, что в очень быстрых последовательных событиях пользовательского интерфейса у нас не хватало памяти. Как вы можете видеть, я «решил» это с помощью грязного хака (поток ожидает 200 мс и дает Android немного времени, чтобы наверстать упущенное).
Я не очень доволен этим по понятным причинам. Во-первых, мой диагноз (что сборка мусора не заканчивается до того, как мы выделим новую память) верен? Во-вторых, я попытался поставить
while(!areaBitmap.isRecycled())
вокруг приращения счетчика после вызова recycle()
, и счетчик остался на нуле. Я вижу смысл в том, чтобы isRecycled()
делал это, но мне нужно что-то вроде isCompletelyRecycled()
метода. У Android есть что-нибудь подобное? В-третьих, если я не могу получить что-либо с этим, есть ли метод «доступной памяти», который я могу использовать, чтобы сказать, собирается ли мой вызов подтолкнуть нас? Я не могу найти один. Было бы неплохо, если бы Android сказал «БОЛЬШЕ ОСНОВНОГО, ДОСТУПНО, НО НЕТ ВАМ», чтобы я мог, возможно, назвать свой цикл ожидания как план Б, или, в конце концов, попробовать что-то менее интенсивное.