Есть ли способ узнать, была ли битмап полностью удален на Android? - PullRequest
0 голосов
/ 08 июля 2011

Я создаю приложение для просмотра, которое вызывает 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 сказал «БОЛЬШЕ ОСНОВНОГО, ДОСТУПНО, НО НЕТ ВАМ», чтобы я мог, возможно, назвать свой цикл ожидания как план Б, или, в конце концов, попробовать что-то менее интенсивное.

Ответы [ 2 ]

2 голосов
/ 08 июля 2011

Память растрового изображения выделяется в собственной куче, поэтому System.gc () не поможет. Нативная куча имеет свой собственный GC, но, очевидно, она не запускается достаточно быстро для вас - и я не знаю ни одного способа ее форсировать (т. Е. Нет собственного аналога System.gc ()).

Вы можете изменить структуру своего приложения, поскольку Никлас А предлагает повторно использовать ваше растровое изображение.

Или вы можете использовать встроенные механизмы мониторинга кучи, подробно описанные в BitmapFactory OOM, сводя меня с ума , чтобы определить, когда безопасно выделять новое растровое изображение.

0 голосов
/ 08 июля 2011

Попробуйте запустить System.gc() вместо сна.


На самом деле я не уверен, поможет ли это, так как растровое изображение кажется в основном нативным кодом, то есть должно бытьвыпущен, как только вызывается recycle.


Мне кажется, что создание нового растрового изображения на каждом событии пользовательского интерфейса кажется плохой идеей, не могли бы вы просто создать одно растровое изображение и редактировать его?1010 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...