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入门到精通教程
查看: 371|回复: 0

【android】解决因为图片太大引起的内存不足问题,Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-20 02:03:22 | 显示全部楼层 |阅读模式

    这个问题很早就遇到了,当时怎么解决的忘记了。今天在做项目的时候又出现了。

    我先是在我自己的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

                  http://blog.csdn.net/yangxyjd/article/details/6932989

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

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2025-2-3 06:04 , Processed in 0.065989 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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