用Bitmap加载图片资源时,报错java.lang.OutOfMemoryError: bitmap size exceeds VM budget的解决办法

http://blog.csdn.net/jason_wks/article/details/7454823

android系统限制,只给图片分配8兆的内存,超过就崩,你图片几十KB,可能是压缩格式的,转换成bitmap就是本来的大小。

在使用模拟器时,出现以上错误,怎么办呢?

1.方法一:增大限制:在设置VM的时候,在Hardware选项中,有一项Max VM application heap size,将该项的值增大(默认值是24,可以增到60等等)

2.方法二:压缩图片,并及时回收不再使用的Bitmap

BitmapFactory.Options.inSampleSize

设置恰当的inSampleSize可以使BitmapFactory分配更少的空间以消除该错误。inSampleSize的具体含义请参考SDK文档。例如:

  1. BitmapFactory.Options opts =  new  BitmapFactory.Options(); 
  2. opts.inSampleSize =  4
  3. Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts); 
BitmapFactory.Options opts =  new  BitmapFactory.Options();
opts.inSampleSize =  4 ;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);


如何设置恰当的inSampleSize

设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。

  1. BitmapFactory.Options opts =  new  BitmapFactory.Options(); 
  2. opts.inJustDecodeBounds =  true
  3. Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts); 
BitmapFactory.Options opts =  new  BitmapFactory.Options();
opts.inJustDecodeBounds =  true ;
Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);


设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。

查看Android源码,Android提供了一种动态计算的方法。

  1. public static int computeSampleSize(BitmapFactory.Options options, 
  2.             int minSideLength, int maxNumOfPixels) { 
  3.         int initialSize = computeInitialSampleSize(options, minSideLength, 
  4.                 maxNumOfPixels); 
  5.         int roundedSize; 
  6.         if (initialSize <= 8) { 
  7.             roundedSize = 1
  8.             while (roundedSize < initialSize) { 
  9.                 roundedSize <<= 1
  10.             } 
  11.         } else
  12.             roundedSize = (initialSize + 7) / 8 * 8
  13.         } 
  14.         return roundedSize; 
  15.     } 
  16.  
  17.     private static int computeInitialSampleSize(BitmapFactory.Options options, 
  18.             int minSideLength, int maxNumOfPixels) { 
  19.         double w = options.outWidth; 
  20.         double h = options.outHeight; 
  21.         int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math 
  22.                 .sqrt(w * h / maxNumOfPixels)); 
  23.         int upperBound = (minSideLength == -1) ? 128 : (int) Math.min( 
  24.                 Math.floor(w / minSideLength), Math.floor(h / minSideLength)); 
  25.         if (upperBound < lowerBound) { 
  26.             // return the larger one when there is no overlapping zone. 
  27.             return lowerBound; 
  28.         } 
  29.         if ((maxNumOfPixels == -1) && (minSideLength == -1)) { 
  30.             return 1
  31.         } else if (minSideLength == -1) { 
  32.             return lowerBound; 
  33.         } else
  34.             return upperBound; 
  35.         } 
  36.     } 
public static int computeSampleSize(BitmapFactory.Options options,
			int minSideLength, int maxNumOfPixels) {
		int initialSize = computeInitialSampleSize(options, minSideLength,
				maxNumOfPixels);
		int roundedSize;
		if (initialSize <= 8) {
			roundedSize = 1;
			while (roundedSize < initialSize) {
				roundedSize <<= 1;
			}
		} else {
			roundedSize = (initialSize + 7) / 8 * 8;
		}
		return roundedSize;
	}

	private static int computeInitialSampleSize(BitmapFactory.Options options,
			int minSideLength, int maxNumOfPixels) {
		double w = options.outWidth;
		double h = options.outHeight;
		int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
				.sqrt(w * h / maxNumOfPixels));
		int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
				Math.floor(w / minSideLength), Math.floor(h / minSideLength));
		if (upperBound < lowerBound) {
			// return the larger one when there is no overlapping zone.
			return lowerBound;
		}
		if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
			return 1;
		} else if (minSideLength == -1) {
			return lowerBound;
		} else {
			return upperBound;
		}
	}



使用该算法,就可动态计算出图片的inSampleSize。

  1. BitmapFactory.Options opts =  new  BitmapFactory.Options(); 
  2.     opts.inJustDecodeBounds =  true
  3.     BitmapFactory.decodeFile(imageFile, opts); 
  4.       
  5.     opts.inSampleSize = computeSampleSize(opts, - 1128 * 128 );        
  6.     opts.inJustDecodeBounds =  false
  7.     try  { 
  8.          Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts); 
  9.          imageView.setImageBitmap(bmp); 
  10.     }  catch  (OutOfMemoryError err) { 
  11.     } 
BitmapFactory.Options opts =  new  BitmapFactory.Options();
	opts.inJustDecodeBounds =  true ;
	BitmapFactory.decodeFile(imageFile, opts);
	 
	opts.inSampleSize = computeSampleSize(opts, - 1 ,  128 * 128 );       
	opts.inJustDecodeBounds =  false ;
	try  {
	     Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts);
	     imageView.setImageBitmap(bmp);
	}  catch  (OutOfMemoryError err) {
	}


另外,可以通过Bitmap.recycle()方法来释放位图所占的空间,当然前提是位图没有被使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值