项目用到加载大图片,app老是出现OOM异常,总结了几点经验,供参考。
1、手动干涉dalvik的堆内存处理效率:
1 private final static float TARGET_HEAP_UTILIZATION = 0.75f;
2 //for same activity
3 public void onCreate()
4 {
5 …………
6 VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
7 …………
8 }
2、手动指定Android堆大小:
1 private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
2 //for same activity
3 public void onCreate()
4 {
5 …………
6 VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE); //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理
7 …………
8 }
3、手动指定回收内存,指定gc:
1 if(bitmap!=null && !bitmap.isRecycled())
2 {
3 bitmap.recycle();
4 System.gc();
5 }
4、图片必须进行缩放,不然多半会出OOM:
1 /**
2 * @param url
3 * 图片的url
4 * @param sc
5 * ,显示的像素大小
6 * @return 返回指定RUL的缩略图
7 *
8 * @author jevan 2012-7-3
9 *
10 */
11 public static Bitmap loadImageFromUrl(String url, int sc)
12 {
13
14 URL m;
15 InputStream i = null;
16 BufferedInputStream bis = null;
17 ByteArrayOutputStream out = null;
18
19 if (url == null)
20 return null;
21 try
22 {
23 m = new URL(url);
24 i = (InputStream) m.getContent();
25 bis = new BufferedInputStream(i, 1024 * 4);
26 out = new ByteArrayOutputStream();
27 int len = 0;
28
29 while ((len = bis.read(isBuffer)) != -1)
30 {
31 out.write(isBuffer, 0, len);
32 }
33 out.close();
34 bis.close();
35 } catch (MalformedURLException e1)
36 {
37 e1.printStackTrace();
38 return null;
39 } catch (IOException e)
40 {
41 e.printStackTrace();
42 }
43 if (out == null)
44 return null;
45 byte[] data = out.toByteArray();
46 BitmapFactory.Options options = new BitmapFactory.Options();
47 options.inJustDecodeBounds = true;
48 BitmapFactory.decodeByteArray(data, 0, data.length, options);
49 options.inJustDecodeBounds = false;
50 int be = (int) (options.outHeight / (float) sc);
51 if (be <= 0)
52 {
53 be = 1;
54 } else if (be > 3)
55 {
56 be = 3;
57 }
58 options.inSampleSize = be;
59 Bitmap bmp =null;
60 try
61 {
62 bmp = BitmapFactory.decodeByteArray(data, 0, data.length, options); //返回缩略图
63 } catch (OutOfMemoryError e)
64 {
65 // TODO: handle exception
66 MainActivity.print("Tile Loader (241) Out Of Memory Error " + e.getLocalizedMessage());
67
68 System.gc();
69 bmp =null;
70 }
71 return bmp;
72 }
把上面几条全部用上,OOM的异常基本上能完全避免!!!
以下内容为转载,收藏。
1 //我们在BitmapManager.instance().decodeFile对图片进行解码,生成Bitmap的时候,我们会发现很多大图片会报OutOfMemoryError的错误,这个时候我们需要改变options里面的一些参数来解决这个问题,不然我们程序就跑不下去了。最简单的方法就是改变options.inSampleSize这个参数,把它增大,就可以解决很多图片OutOfMemoryError的问题。
2 //下面是一个使用了这个方式的代码
3 public static Bitmap makeBitmap(String path, int minSideLength, int maxNumOfPixels, BitmapFactory.Options options)
4 {
5 Bitmap b = null;
6 Log.i(TAG, "makeBitmap : path = " + path);
7 if (path == null)
8 return null;
9 File f = new File(path);
10
11 //try {
12 // b = BitmapManager.instance().decodeFile(f, null);
13 //} catch (OutOfMemoryError ex) {
14 // Log.e(TAG, "Got oom exception, we may try one more time, using Options:" + ex.getMessage());
15 if (options == null)
16 {
17 options = new BitmapFactory.Options();
18 }
19
20 try
21 {
22 options.inJustDecodeBounds = true;
23 BitmapManager.instance().decodeFile(f, options);
24 if (options.mCancel || options.outWidth == -1 || options.outHeight == -1)
25 {
26 return null;
27 }
28 options.inSampleSize = computeSampleSize(options, minSideLength, maxNumOfPixels);
29 options.inJustDecodeBounds = false;
30 options.inDither = true;
31 options.inPreferredConfig = null;//Bitmap.Config.ARGB_8888;
32
33 b = BitmapManager.instance().decodeFile(f, options);
34 } catch (OutOfMemoryError ex2)
35 {
36 Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "
37 + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex2);
38 try
39 {
40 options.inSampleSize += 1;
41 options.inJustDecodeBounds = false;
42 options.inDither = true;
43 options.inPreferredConfig = null;
44 b = BitmapManager.instance().decodeFile(f, options);
45 } catch (OutOfMemoryError e)
46 {
47 Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize + " minSideLength = "
48 + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, e);
49 try
50 {
51 options.inSampleSize += 1;
52 options.inJustDecodeBounds = false;
53 options.inDither = true;
54 options.inPreferredConfig = null;
55 b = BitmapManager.instance().decodeFile(f, options);
56 } catch (OutOfMemoryError ex)
57 {
58 Log.e(TAG, "Got oom exception when retry the 2nd time,options.inSampleSize= " + options.inSampleSize
59 + " minSideLength = " + minSideLength + " maxNumOfPixels =" + maxNumOfPixels, ex);
60 return null;
61 }
62 }
63 }
64
65 //}
66 return b;
67 }
1 //另外一处代码
2 public static Bitmap getBitpMap(InputStream is)
3 {
4 ParcelFileDescriptor pfd;
5 try
6 {
7 pfd = getContentResolver().openFileDescriptor(uri, "r");
8 } catch (IOException ex)
9 {
10 return null;
11 }
12 java.io.FileDescriptor fd = pfd.getFileDescriptor();
13 BitmapFactory.Options options = new BitmapFactory.Options();
14 //先指定原始大小
15 options.inSampleSize = 1;
16 //只进行大小判断
17 options.inJustDecodeBounds = true;
18 //调用此方法得到options得到图片的大小
19 BitmapFactory.decodeFileDescriptor(fd, null, options);
20 //BitmapFactory.decodeStream(is, null, options);
21 //我们的目标是在800pixel的画面上显示。
22 //所以需要调用computeSampleSize得到图片缩放的比例
23 options.inSampleSize = computeSampleSize(options, 800);
24 //OK,我们得到了缩放的比例,现在开始正式读入BitMap数据
25 options.inJustDecodeBounds = false;
26 options.inDither = false;
27 options.inPreferredConfig = Bitmap.Config.ARGB_8888;
28
29 //根据options参数,减少所需要的内存
30 // Bitmap sourceBitmap = BitmapFactory.decodeFileDescriptor(fd, null, options);
31 Bitmap sourceBitmap = BitmapFactory.decodeStream(is, null, options);
32 return sourceBitmap;
33 }
34
35 //这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如2即1/2,3即1/3
36 static int computeSampleSize(BitmapFactory.Options options, int target)
37 {
38 int w = options.outWidth;
39 int h = options.outHeight;
40 int candidateW = w / target;
41 int candidateH = h / target;
42 int candidate = Math.max(candidateW, candidateH);
43 if (candidate == 0)
44 return 1;
45 if (candidate > 1)
46 {
47 if ((w > target) && (w / candidate) < target)
48 candidate -= 1;
49 }
50 if (candidate > 1)
51 {
52 if ((h > target) && (h / candidate) < target)
53 candidate -= 1;
54 }
55 //if (VERBOSE)
56 Log.v(TAG, "for w/h " + w + "/" + h + " returning " + candidate + "(" + (w / candidate) + " / " + (h / candidate));
57 return candidate;
58 }
|