Android加载大图片OOM异常解决

项目用到加载大图片,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     //这个函数会对图片的大小进行判断,并得到合适的缩放比例,比如21/2,31/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     }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值