android createbitmap,慎用Bitmap.createBitmap

碰到一个诡异的bitmap回收问题,抛出了使用了recycled的bitmap。

最终分析是Bitmap.createBitmap(Bitmap bitmap)造成的,Bitmap.createBitmap(。。。)都有此可能。

这个方法的注释如下:

Returns an immutable bitmap from subset of the source bitmap, transformed by the optional matrix. The new bitmap may be the same object as source, or a copy may have been made. It is initialized with the same density as the original bitmap. If the source bitmap is immutable and the requested subset is the same as the source bitmap itself, then the source bitmap is returned and no new bitmap is created.

所以你在使用它的时候很可能会返回给你一个你传进来的bitmap。

所以如果你按照你的设计把那个认为是临时变量的bitmap回收掉之后,殊不知不该回收的也回收了。

之前好像在哪里看到过有朋友说用Bitmap.createBitmap构造出来的bitmap回收的时候把传入的也连带回收了,并且没找到原因。当时也没在意,并且那边也没有结贴。现在想起来,估计就是这个方法造成的。

翻看Bitmap.java,找到createBitmap都是调用的这个重构方法:

public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,

Matrix m, boolean filter) {

checkXYSign(x, y);

checkWidthHeight(width, height);

if (x + width > source.getWidth()) {

throw new IllegalArgumentException("x + width must be <= bitmap.width()");

}

if (y + height > source.getHeight()) {

throw new IllegalArgumentException("y + height must be <= bitmap.height()");

}

// check if we can just return our argument unchanged

if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&

height == source.getHeight() && (m == null || m.isIdentity())) {

return source;

}

int neww = width;

int newh = height;

Canvas canvas = new Canvas();

Bitmap bitmap;

Paint paint;

Rect srcR = new Rect(x, y, x + width, y + height);

RectF dstR = new RectF(0, 0, width, height);

Config newConfig = Config.ARGB_8888;

final Config config = source.getConfig();

// GIF files generate null configs, assume ARGB_8888

if (config != null) {

switch (config) {

case RGB_565:

newConfig = Config.RGB_565;

break;

case ALPHA_8:

newConfig = Config.ALPHA_8;

break;

//noinspection deprecation

case ARGB_4444:

case ARGB_8888:

default:

newConfig = Config.ARGB_8888;

break;

}

}

if (m == null || m.isIdentity()) {

bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());

paint = null;   // not needed

} else {

final boolean transformed = !m.rectStaysRect();

RectF deviceR = new RectF();

m.mapRect(deviceR, dstR);

neww = Math.round(deviceR.width());

newh = Math.round(deviceR.height());

bitmap = createBitmap(neww, newh, transformed ? Config.ARGB_8888 : newConfig,

transformed || source.hasAlpha());

canvas.translate(-deviceR.left, -deviceR.top);

canvas.concat(m);

paint = new Paint();

paint.setFilterBitmap(filter);

if (transformed) {

paint.setAntiAlias(true);

}

}

// The new bitmap was created from a known bitmap source so assume that

// they use the same density

bitmap.mDensity = source.mDensity;

canvas.setBitmap(bitmap);

canvas.drawBitmap(source, srcR, dstR, paint);

canvas.setBitmap(null);

return bitmap;

}

在这个方法里有如下逻辑:

// check if we can just return our argument unchanged

if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&

height == source.getHeight() && (m == null || m.isIdentity())) {

return source;

}

因此,在满足这个逻辑的情况下,createBitmap把传进来的source直接返回了。

所以对这个方法慎用吧,需要保证创建一个拷贝的可以尝试使用Bitmap.copy(Config config, boolean isMutable)来完成设计上的需要。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值