android L 在调用Bitmap.createBitmap时出现同步问题,带有缩略图jpg照片才会出现,求大神指导
多个线程同时调用
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)
这个方法时,传入的source参数经过打断点检查是正确的,其他的参数也都是一样的,
出现的问题是:
在调用上面的方法后
返回的Bitmap会出现纯黑色的图片,高度和宽度都没有问题
只是每个像素点都是黑色的,查看buffer里的数组为[0,0,0,-1,0,0,0,-1...]
测试结果:
1.在调用createBitmap方法的语句上加上synchronized,问题消失!
如:synchronized(Bitmap.class) {
Bitmap bitmap = createBitmap(source,0,0, width, height,matrix, true);//matrix做了图像的旋转和缩放
}
2.出现问题的图片是不是固定的(只有1~2张图片是正常的,其他都黑了,正常的图片也是随机的,无法确定)。
3.本人测试发现只有图片带有resources属性为thumbnail的才会出现黑图。
经过一番源码查找,没有发现哪里有会出现同步问题的公共资源,下面把源码贴出来,求大神分析指导下!!!
/*调用的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;
bitmap.setHasAlpha(source.hasAlpha());
bitmap.setPremultiplied(source.mRequestPremultiplied);
canvas.setBitmap(bitmap);
canvas.drawBitmap(source, srcR, dstR, paint);
canvas.setBitmap(null);
return bitmap;
}
//上面createBitmap方法调用的createBitmap方法
private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
Config config, boolean hasAlpha) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
if (display != null) {
bm.mDensity = display.densityDpi;
}
bm.setHasAlpha(hasAlpha);
if (config == Config.ARGB_8888 && !hasAlpha) {
nativeErase(bm.mNativeBitmap, 0xff000000);
}
// No need to initialize the bitmap to zeroes with other configs;
// it is backed by a VM byte array which is by definition preinitialized
// to all zeroes.
return bm;
}
C++不是特别熟,源码看的一知半解,Bitmap.cpp和SKBitmap.cpp的源码没看出什么问题。。。