2012-01-18 109 views
1

我收到错误java.lang.OutOfMemoryError: bitmap size exceeds VM budgetAndroid位图创建OutOfMemory错误

创建用于手动绘制折线图的位图时会出现这种情况。

width = display.getWidth() - 10; 
height = width * 4/5; 
Bitmap emptyBmap = Bitmap.createBitmap(width, height, Config.ARGB_8888); 
Bitmap charty = createMyGraphAndStuff(emptyBmap); 

它看起来像分配的总内存大约700 Kb,不合理的数额。

我在文件中创建位图时看到了其他解决方案,但在这里我自己生成一个位图。我如何最小化内存占用?

这里的一些代码给你它正在做什么更好的主意:

public Bitmap DrawTheGraphAndStuff(Bitmap bitmap, String[] scores) 
{ 
     Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); 
     Canvas canvas = new Canvas(output); 

     drawTheGridLines(canvas);         

     plotTheDataPoints(canvas , scores , "the title" , 0);  

     canvas.drawBitmap(bitmap, rect, rect, paint); 

     return output; 
} 
+0

你为什么不发布你的“createMyGraphAndStuff(Bitmap b)”函数。顺便说一句,在这个名字! – L7ColWinters 2012-01-18 02:46:53

+0

你可以粘贴你的'createMyGraphAndStuff'代码吗? – idiottiger 2012-01-18 02:58:50

+0

什么是createMyGraphAndStuff? – 2012-01-18 03:19:46

回答

6

当OOM发生,给些建议:

1.need知道OOM发生位置,日志信息是不够

2,大部分时间是位图的过程,所以你需要知道如何太大的关于所使用的存储器图像:

下式:w * h * every pixel token memory in byte,如果ConfigConfig.ARGB_8888,每个像素令牌存储器是4bytes,如果是Config.RGB_565,是2bytes

3.also,你需要知道在你的设备中的每一个应用程序的内存限制:

ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
    activityManager.getMemoryClass(); //return the memory size limit in MB 

3.如果位图没有再使用,尽量recyle()

4.如果开始的位图过程中,内存几乎是最大内存限制,所以使用adb shell dumpsys meminfo $pid来检查内存使用情况,同样ddms - allocation tracker也很有用

1

如果你的显示宽度为480,您的位图是470x376。每个像素4个字节,即706880字节。使用较少内存的唯一方法是使位图变小。

1

基本上回收你的位图,你不应该再有这个问题了。使用recycle()。

+0

好点,在你将emptyBmap传递给createMyGraphAndStuff()之后,你可以回收那个,因为java通过拷贝而不是指针传递对象。 – L7ColWinters 2012-01-18 02:57:21

+0

so emptyBmap.recycle()会照顾它吗? – Allen 2012-01-18 05:30:56

1

这不是一个真正需要解决的问题,这是一个需要解决的设计问题。你不能假设任何关于将会提供给你的堆。以下是一些可能对你有帮助的事情。

  • 您可能想要认真考虑的一件事是加载位图的压缩版本:在加载位图之前找出堆上可用的内存量。基于此,计算您要加载的位图的大小,从中计算高度和宽度,然后加载位图。
  • 确保您没有泄漏Bitmaps。这是人们遇到的主要问题之一。从泄漏意见到泄漏活动,这可能以多种方式发生。要检查此,配置文件您的工作记忆
  • 当没有内存泄漏时,GC会自动清除位图。在3之前。0设备,你必须调用recycle(),因为GC没有做好。这在3.0之后的设备中不是必需的。虽然要小心,如果您在正在使用的位图上调用recycle(),则在ImageView中说,您会得到一个异常。
0

你总是可以尝试使用软参考位图,但它们可能会比你需要的更快地收集垃圾。