
在 Android 中,对远程获取的 Bitmap 进行二次处理(如变暗)时,若直接复用原对象会导致原始图像也被修改;正确做法是先调用 copy() 创建独立副本,再对副本执行绘制操作。
在 android 中,对远程获取的 bitmap 进行二次处理(如变暗)时,若直接复用原对象会导致原始图像也被修改;正确做法是先调用 `copy()` 创建独立副本,再对副本执行绘制操作。
当你通过网络加载一张图片并希望生成两个不同样式的 Bitmap(例如一个原始版本、一个叠加灰黑色蒙层的“暗化”版本),切忌直接将原 Bitmap 对象传入修改逻辑——因为 Bitmap 是可变对象,所有引用都指向同一内存块。你当前代码中:
Bitmap darkImage = darkImage(remoteImage); // ❌ remoteImage 本身被修改!
而 darkImage() 方法内部使用 Canvas 直接在原图上绘制半透明黑色(drawARGB(175, 0, 0, 0))并重绘自身,这会永久改变 remoteImage 的像素数据,导致原始图像丢失。
✅ 正确解法:在修改前显式创建不可变/可变副本:
asyncTask(new GetRemoteImage(), (remoteImage) -> {
// ✅ 创建独立副本(注意:需确保原图支持 copy,如非 null 且 config 不为 null)
Bitmap remoteImageCopy = remoteImage.copy(remoteImage.getConfig(), true);
// ✅ 对副本进行暗化处理,原始 remoteImage 保持不变
Bitmap darkImage = darkImage(remoteImageCopy);
// 后续可同时使用:remoteImage(原始)、darkImage(已暗化)
});
⚠️ 关键注意事项:
-
copy()的第二个参数isMutable推荐设为true,否则返回的不可变Bitmap无法用于Canvas绘制; - 确保
remoteImage.getConfig() != null,常见安全写法:Bitmap remoteImageCopy = remoteImage.copy( remoteImage.getConfig() != null ? remoteImage.getConfig() : Bitmap.Config.ARGB_8888, true ); -
copy()会分配新内存,注意内存管理,及时回收不再使用的Bitmap(尤其在onDestroy()或onDetachedFromWindow()中调用recycle()); - 若原始
Bitmap来自BitmapFactory.decode...,默认已是可变的(API ≥ 28)或需手动设置Options.inMutable = true(旧版本)。
总结:Bitmap.copy() 是实现“一图多用、互不干扰”的核心手段。只要在任何修改操作前完成一次深拷贝,即可安全地并行维护多个风格化版本,避免重复网络请求与资源浪费。










