【问题标题】:Should I recycle my bitmaps after a resize?我应该在调整大小后回收我的位图吗?
【发布时间】:2014-03-07 21:03:26
【问题描述】:

我有一个实用方法(如下),它可以调整位图的大小并返回一个新版本。由于我对很多图像执行此操作,并且我想减少内存不足的机会,因此我在使用后回收了位图。

这几乎适用于所有设备。但是,我注意到三星 Galaxy Tab 3(10 英寸)和注释 10.1(2014)我得到以下堆栈跟踪:

java.lang.IllegalArgumentException: Cannot draw recycled bitmaps
at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:756)
at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:104) 

以下是我的调整大小代码:

private static Bitmap resizeBitmap(int newWidth, int newHeight, Bitmap bitmapResize) {
    if (bitmapResize == null) {
        return null;
    }

    int width = bitmapResize.getWidth();
    int height = bitmapResize.getHeight();

    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;

    Matrix matrix = new Matrix();
    matrix.postScale(scaleWidth, scaleHeight);

    Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmapResize,
            newWidth, newHeight, true);

    //SHOULD I DO THIS???
    bitmapResize.recycle();
    return resizedBitmap;
}

我还没有弄清楚为什么几乎所有设备都可以工作,除了那 2 个(可能还有更多)。模拟器也没有问题。

值得注意的是,并非所有图像都会出现“无法绘制回收位图”错误。只有一些。但它始终是相同的图像。

(如果使用,我的应用程序运行在 2.2 以上)

【问题讨论】:

  • mm...也许我应该改写标题 - 我想我应该问我是否应该在调整大小时回收?
  • 显然不是,因为你不能画然后...

标签: android


【解决方案1】:

我已设法找到解决问题的方法。事实证明,如果调整大小的宽度/高度与原始图像匹配,则可以将原始图像作为优化传回。

我想在某些设备上,我的计算导致我试图将图像调整为现有大小。当我回收“旧”位图时,我也在回收调整大小的位图。

解决办法是把我的代码改成说

if (bitmapResize!=resizedBitmap )
    bitmapResize.recycle();

我发现此对话涵盖了我的问题(我在最初搜索该问题时没有找到)

https://groups.google.com/forum/#!topic/android-developers/M6njPbo3U0c

【讨论】:

  • 进行此更改并发布我的代码后,它确实解决了问题。
【解决方案2】:

您可以简单地使用输入位图参考作为输出。这样您的输入位图将被覆盖,您不需要回收它。

种类:

private static Bitmap resizeBitmap(int newWidth, int newHeight, Bitmap bitmapResize) {
if (bitmapResize == null) {
    return null;
}

int width = bitmapResize.getWidth();
int height = bitmapResize.getHeight();

float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;

Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);

return Bitmap.createScaledBitmap(bitmapResize,
        newWidth, newHeight, true);

}

【讨论】:

  • 我试过这种方法,回收似乎可以更好地防止内存不足异常
  • 根据另一篇文章,在旧版本的 android 上可能需要回收:stackoverflow.com/questions/11954435/…。我没有提到它(直到现在),但我的应用确实在 android 2.2 / level 8 上运行。
  • 你没有那样做。您没有覆盖您的输入位图(无论这意味着什么)。您根本没有创建一个局部变量来保存它,这根本不会改变。
【解决方案3】:

我在 on of ma 游戏中遇到了类似的问题,根据我的经验,你做的事情是正确的。它是回收旧位图并防止 OutOfMemoryExceptions 的正确位置,请记住,此位图实例将不再可用。

【讨论】:

  • 谢谢,知道为什么我在几个设备上得到“无法绘制回收的位图”吗?
  • 您有使用旧位图的视图吗?这种错误主要是线程安全问题。
  • 我不使用原始图像 - 在银河选项卡 3 上也始终如一,但我无法在其他设备上复制 - 我想线程问题会在所有设备上发生而不是一致。
猜你喜欢
  • 2011-11-08
  • 2014-04-19
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多