【android】解决因为图片太大引起的内存不足问题,Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
这个问题很早就遇到了,当时怎么解决的忘记了。今天在做项目的时候又出现了。
我先是在我自己的Lenovo A750手机上调试没问题,放到HTC的G18上报错!放到电脑的2.2模拟器上报错!这个问题一出现瞬间发狂了~
好吧,来了我就把它解决掉!
先看看我的问题出在哪里:
1 LayoutInflater inflater=getLayoutInflater();
2 list=new ArrayList<View>();
3 list.add(inflater.inflate(R.layout.item1, null));//就在这!
4 list.add(inflater.inflate(R.layout.item2, null));
5 list.add(inflater.inflate(R.layout.item3, null));
6 list.add(inflater.inflate(R.layout.item4, null));
我在每一个item中只加了一个imageview控件,图片的src在xml中就定好了。在添加到list中的时候报错了。
在网上找引起报错的原因没直接找到,但找到一个相关的:
“当图片过大,或图片数量较多时使用BitmapFactory解码图片会出java.lang.OutOfMemoryError: bitmap size exceeds VM budget,要想正常使用则需分配更少的内存,具体的解决办法是修改采样值BitmapFactory.Options.inSampleSize”
同样的错误错误效果,他们出错是在读取图片文件的时候报错,看看自己的代码,想要修改Options.inSampleSize要把每一个item中的imageview控件拿出来设置他们的setBackgroundDrawable。
如下:
1 LayoutInflater inflater=getLayoutInflater();
2 list=new ArrayList<View>();
3
4 View view = inflater.inflate(R.layout.item1, null);
5 view.findViewById(R.id.well_item).setBackgroundDrawable(new BitmapDrawable(readBitMap(this.getApplicationContext(), R.drawable.b1)));
6 list.add(view);
7
8 View view2 = inflater.inflate(R.layout.item2, null);
9 view2.findViewById(R.id.well_item).setBackgroundDrawable(new BitmapDrawable(readBitMap(this.getApplicationContext(), R.drawable.b2)));
10 list.add(view2);
11
12 View view3 = inflater.inflate(R.layout.item3, null);
13 view3.findViewById(R.id.well_item).setBackgroundDrawable(new BitmapDrawable(readBitMap(this.getApplicationContext(), R.drawable.b3)));
14 list.add(view3);
15
16 View view4 = inflater.inflate(R.layout.item4, null);
17 view4.findViewById(R.id.imageView1).setBackgroundDrawable(new BitmapDrawable(readBitMap(this.getApplicationContext(), R.drawable.b4)));
18 list.add(view4);
19
上面的readBitMap方法就是解决问题的关键:
1 public static Bitmap readBitMap(Context context, int resId){
2 BitmapFactory.Options opt = new BitmapFactory.Options();
3 opt.inPreferredConfig = Bitmap.Config.RGB_565;
4 opt.inPurgeable = true;
5 opt.inInputShareable = true;
6 opt.inSampleSize = computeSampleSize(opt, -1, 128*128); //计算出图片使用的inSampleSize
7 opt.inJustDecodeBounds = false;
8 //获取资源图片
9 InputStream is = context.getResources().openRawResource(resId);
10 return BitmapFactory.decodeStream(is,null,opt);
11 }
12
13 public static int computeSampleSize(BitmapFactory.Options options,
14 int minSideLength, int maxNumOfPixels) {
15 int initialSize = computeInitialSampleSize(options, minSideLength,maxNumOfPixels);
16
17 int roundedSize;
18 if (initialSize <= 8 ) {
19 roundedSize = 1;
20 while (roundedSize < initialSize) {
21 roundedSize <<= 1;
22 }
23 } else {
24 roundedSize = (initialSize + 7) / 8 * 8;
25 }
26
27 return roundedSize;
28 }
29
30 private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {
31 double w = options.outWidth;
32 double h = options.outHeight;
33
34 int lowerBound = (maxNumOfPixels == -1) ? 1 :
35 (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
36 int upperBound = (minSideLength == -1) ? 128 :
37 (int) Math.min(Math.floor(w / minSideLength),
38 Math.floor(h / minSideLength));
39
40 if (upperBound < lowerBound) {
41 // return the larger one when there is no overlapping zone.
42 return lowerBound;
43 }
44
45 if ((maxNumOfPixels == -1) &&
46 (minSideLength == -1)) {
47 return 1;
48 } else if (minSideLength == -1) {
49 return lowerBound;
50 } else {
51 return upperBound;
52 }
53 }
“他们还提供一个方法是Bitmap.recycle()方法来释放位图所占的空间,当然前提是位图没有被使用”。本次是在加载第一个的时候就已经报错。不在考虑了额。
参考链接:http://www.cnblogs.com/xiyo/archive/2012/05/26/2519028.html