【问题标题】:OutOfMemoryError when using 2 bitmaps使用 2 个位图时出现 OutOfMemoryError
【发布时间】:2013-06-05 10:45:36
【问题描述】:

我的主页布局中有 2 个ImageView,它们的内容来自放置在 SD 卡上的图像,如下面的代码 sn-p 所示:

try {
        String tempPath1 = Environment.getExternalStorageDirectory()
                + File.separator + "Clipping_Pictures" + File.separator
                + "06-05-2013_02-06-09pm.png";
        File f = new File(tempPath1);
        Bitmap b = null, b2 = null;
        b = BitmapFactory.decodeFile(f.getPath());

        if (f.exists()) {
            ivClip1.setImageBitmap(b);//ivClip1 is ImageView
        }

        tempPath1 = Environment.getExternalStorageDirectory()
                + File.separator + "Clipping_Pictures" + File.separator
                + "06-05-2013_02-06-33pm.png";
        f = new File(tempPath1);
        b2 = BitmapFactory.decodeFile(f.getPath());

        if (f.exists()) {
            ivClip2.setImageBitmap(b2);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

当我第一次加载应用程序时,它会在各自的图像视图上显示两个图像。但在第二次启动后,应用程序崩溃并出现以下异常:
OutOfMemoryError: bitmap size超出 VM budget

请注意两个资源图像是 .png,每个大小约为 850kb,我猜应该没问题。

在 SO 和 Internet 上有类似的主题,我尝试了他们建议的一些解决方案,但似乎没有一个有效。

任何帮助表示赞赏。

【问题讨论】:

  • '请注意,两个资源图像是 .png,大小约为 850kb',这无关紧要。重要的是位图的宽度和高度
  • 大约。 2000x2600
  • 每个位图需要大约 20MB 的内存。位图需要宽*高*4 字节的内存
  • 你能告诉我你是怎么得出这个数字的吗:20MB ???
  • 您应该在关闭应用时为每个位图调用 'recycle()' 方法,如果不再需要则关闭 Activity。

标签: android android-layout bitmap out-of-memory


【解决方案1】:

如果您在 wards 上为 Android 3.0 构建应用程序,则可以在清单文件的应用程序标记中使用 android:largeHeap="true" 属性。 这样做,希望您的应用不会因为内存不足而崩溃。

示例如下:

应用

android:allowBackup="true"
android:icon="@drawable/icon_96x96"
android:label="@string/app_name"
android:largeHeap="true"
android:theme="@android:style/Theme.NoTitleBar" 

谢谢!

【讨论】:

  • 可惜了。我的应用程序的最低支持是 v2.2 :(
【解决方案2】:

这是因为您的位图尺寸较大。使用以下代码压缩您的位图:

Bitmap ShrinkBitmap(byte[] file, int width, int height){

         BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
            bmpFactoryOptions.inJustDecodeBounds = true;
            Bitmap bitmap = BitmapFactory.decodeByteArray(file, 0, file.length, bmpFactoryOptions);


            int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
            int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);

            if (heightRatio > 1 || widthRatio > 1)
            {
             if (heightRatio > widthRatio)
             {
              bmpFactoryOptions.inSampleSize = heightRatio;
             } else {
              bmpFactoryOptions.inSampleSize = widthRatio;
             }
            }

            bmpFactoryOptions.inJustDecodeBounds = false;
            bitmap = BitmapFactory.decodeByteArray(file, 0, file.length, bmpFactoryOptions);
         return bitmap;
        }

【讨论】:

  • 第一个参数是byte[] file。如果我发送Bitmap bitmap,那么Bitmap bitmap = BitmapFactory.decodeByteArray(file, 0, file.length, bmpFactoryOptions); 将更改为Bitmap bitmap = BitmapFactory.decodeByteArray(bitmap, bmpFactoryOptions);,对吗?
  • 很抱歉,我对聊天会话不太了解。可以给我聊天链接吗?
  • 你没有聊天经验。??
【解决方案3】:

您是从 onCreate() 还是从 onResume() 执行所有这些代码?

您可以在尝试再次加载图像之前尝试清理视图(ivClip1.setImageBitmap(null) 或轻量级图像),因为在解码两个位图时,您在显示时仍然在内存中保留先前的实例。

【讨论】:

  • onCreate()。清理视图是什么意思?
  • 我建议调用 ivClip1.setImageBitmap(null),如果不起作用,你可以尝试设置一个小空图像(例如可能说“正在加载”的标记图像) ivClip1.setImageResource (R.drawable.my_little_marker_image);
【解决方案4】:

您可以添加此行来调整位图大小,然后使用它

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file),null,options);

计算样本大小和减小位图大小的方法

private Bitmap decodeFile(File f){
    try {
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

        final int REQUIRED_SIZE=70;

        //Find the correct scale value. It should be the power of 2.
        int scale=1;
        while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
            scale*=2;

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}
    return null;
}

【讨论】:

猜你喜欢
  • 2014-08-13
  • 1970-01-01
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多