Android: 使用临时位图出现“尝试使用已回收的位图”错误

20

我的应用程序可以加载相当大的图像。为了节约内存,我正在尝试使用临时位图来加载图像,然后在转换后使用另一个位图来显示最终图像:

.....
finalBitmap.recycle();
finalBitmap = null;
Bitmap tempBitmap  = BitmapFactory.decodeStream(fin, ...);
finalBitmap = Bitmap.createBitmap(tempBitmap, ....);
imgview.setImageBitmap(finalBitmap);
.....

现在,我们在这一点上已经完成了临时位图(tempBitmap)的使用,它仅需要将解码后的位图传递到createBitmap中的转换步骤。所以:

.....
tempBitmap.recycle();
tempBitmap = null;
.....
而且......它会因为对tempBitmap的回收导致"trying to use a recycled bitmap"错误,特别是因为tempBitmap没有被显示,只在那里使用了一下。

这里出了什么问题?我应该只在整个过程中使用"finalBitmap"并依靠createBitmap来管理它(finalBitmap = Bitmap.createBitmap(finalBitmap, ....))吗?我看不出会导致这样失败的tempBitmap上有什么持续的依赖关系。

编辑: 是的,空值分配似乎会导致适当的、最终的垃圾回收,但我对为什么在这种情况下对一个临时位图进行recycle()如此困惑。我有一种印象,createBitmap()正在保留对它的引用,但为什么以及多长时间保留呢?
1个回答

25

来自 Android documentation

从指定的源位图子集返回一个不可变的位图。新位图可能是与源相同的对象,也可能是已经复制。

看起来 createBitmap 函数有可能重用您提供的位图。如果是这种情况,则不应回收临时位图,因为最终位图正在使用它。您可以做的一件事是

if(tempBitmap != finalBitmap) {
   tempBitmap.recycle();
}

只有在tempBitmap与finalBitmap不相同时,才应该进行tempBitmap的回收。至少文档是这样暗示的。


1
我错过了关于它可能是同一个对象的那一部分。我的将temp设置为null并不会产生副作用,因为它并没有真正释放对象,而recycle()则直接影响它。嗯,我接受你的答案,并希望你能给我的问题点赞(因为我认为这对人们来说是有用的信息)。 - MartyMacGyver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接