我正在创建一个调用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);
我遇到的问题是,在非常快速的连续UI事件中,我们的内存不足。正如你所看到的那样,我已经通过肮脏的黑客“解决”了这个问题(该线程等待了200ms并为Android提供了一些时间来赶上)。
由于显而易见的原因,我对此并不满意。首先,我的诊断(垃圾收集在我们分配新内存之前没有完成)是否正确?其次,我试着把
while(!areaBitmap.isRecycled())
在recycle()
调用后计数器增量附近,并且计数器保持为零。我看到isRecycled()
执行此操作的意义,但我需要类似isCompletelyRecycled()
方法的内容。 Android有这样的东西吗?第三,如果我无法通过它获得任何目标,是否有“可用内存”方法我可以用来判断我的电话是否会推动我们过来?我找不到一个。如果Android会为您提供更多核心可用,那么我可以将我的等待循环称为计划B,或者最终尝试不那么密集的东西。
答案 0 :(得分:2)
位图内存在本机堆中分配,因此System.gc()无济于事。本机堆有自己的GC,但很明显它并没有足够快地为你踢 - 而且我不知道有任何强制它的方法(即没有System.gc()的原生模拟)。
您可以更改应用程序的结构,因为Nicklas A建议重新使用您的位图。
或者您可以使用BitmapFactory OOM driving me nuts中详述的本机堆监视机制来确定分配新位图的安全时间。
答案 1 :(得分:0)
尝试运行System.gc()
而不是睡眠。
实际上我不确定这是否有用,因为位图似乎主要是本机代码,这意味着它应该在调用回收时立即释放。
对我来说,似乎在每个UI事件上创建一个新的位图似乎是一个坏主意,难道你不能只创建一个位图并编辑那个位图吗?