碰到一个诡异的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)来完成设计上的需要。 |
小黑屋|管理员QQ:44994224|邮箱(t268studio@gmail.com)|Archiver|MCLOUDER
GMT+8, 2024-5-4 16:50 , Processed in 0.030464 second(s), 18 queries .
Powered by Discuz! X3.4
© 2001-2017 Comsenz Inc.