Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 392|回复: 0

Android加载大图片OOM异常解决

[复制链接]
  • TA的每日心情
    奋斗
    4 天前
  • 签到天数: 789 天

    [LV.10]以坛为家III

    2049

    主题

    2107

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    722638
    发表于 2021-6-3 11:14:57 | 显示全部楼层 |阅读模式

    项目用到加载大图片,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     }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-9-10 02:10 , Processed in 4.993845 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表