zoukankan      html  css  js  c++  java
  • 【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

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

  • 相关阅读:
    arcgis10.2转shp文件中文乱码问题解决方案
    Android Context作为参数传递this
    andriod inputbox
    andriod inputType
    《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)(转)
    终于理解了什么是LGPL
    产品经理如何与强势的技术沟通? 技术比较有资历,会以技术无法实现等方面的原因拒绝处理产品提出的需求。 你们是否遇到这样的技术? 产品懂技术的话,是不是会好一些,因为可以和技术说“行话”了,并且产品懂技术就不会被忽悠了。
    Core Dump总结
    LIBRARY_PATH是编译时候用的,LD_LIBRARY_PATH是程序运行是使用的
    如何禁止C++默认成员函数
  • 原文地址:https://www.cnblogs.com/winxiang/p/2700100.html
Copyright © 2011-2022 走看看