在对象上保留Bitmap引用是否危险?

时间:2014-05-26 16:12:06

标签: android bitmap

我正在使用一些类,这些类包含对Bitmap的引用,如下所示:

class Picture {
    private String localPath;
    private Bitmap bitmap;
    // setters and getters....
}

然后在某些片段上,我使用picture.setBitmap(BitmapUtils.decodeBitmap(picture.getLocalPath, size));获取引用,然后将其设置为ImageView。但我从未明确地bitmap.recycle()bitmap = null;

我不确定位图在内部如何工作以及为什么GC在某些情况下不会收集它们,所以我想知道我在做什么可能会导致内存泄漏,我该如何防止这种情况,鉴于位图引用仅作为持有者存储在对象上

编辑,因为我对Bitmap的处理方式似乎有点混乱,我会再解释一下。信息系统中的业务模型定义了几个将图像作为属性的实体(例如,用户具有配置文件名称的配置文件和配置文件图片)。

确实如此,在这种情况下,您通常会将图片路径保留为属性而不是图片本身。但由于我从Android相机拍摄了几张照片,我将其保存到列表中以执行批量操作。您可以看到它就像实体作为图片本身的持有者一样,因为您需要引用每张图片以对它们执行批处理操作。

2 个答案:

答案 0 :(得分:1)

编辑回答: 我读了你编辑过的问题,我仍然相信你不应该拿着位图,我会解释原因。

  

我正从Android相机拍摄几张照片,我将其保存到列表中以执行批量操作。

那个“清单”,它会增长多少? 1或2张图片?好几张照片?它是无限的,只取决于用户的使用情况?

所以让我们想象一下现在非常普通的图像尺寸,即使是中档手机也有,5 MP。这是2560x1920像素,精确到4.915.200像素。如果您使用的是最优质的位图(Config.ARGB_8888),则每个像素将占用4个字节的内存。这将导致:

4.915.200 x 4 / 1024 / 1024 (in megabytes)

因此每张图片每个位图需要 18.75兆字节的RAM空间。

我最近没有检查Android VM堆大小,但第一个ICS设备的堆大小约为48mb。这意味着您的代码加上一些图片和您的应用会抛出OutOfMemoryError

总结:

我仍然认为你应该只保存对摄像机生成的JPG的String引用(如果你没有生成JPG而只获取Bitmap,请继续保存Bitmap { 1}}在磁盘using this code中)然后在您的数组上排队String,一旦您的代码到达字符串,然后您解码您的位图,进行处理,然后立即隐藏它。

原始回答:

我可能错了,但我相信你正试图重新发明轮子,你不应该。

在我看来,你正在尝试进行某种类型的位图缓存/解码,这是一个相当复杂和微妙的主题,因为它涉及线程和移动内存限制。

说我所有的建议只是使用一个已经为你处理所有这些的库。我个人最喜欢的是毕加索http://square.github.io/picasso/

有了它,你所要做的就是:

Picasso.with(context).load(path).into(imgView);

就是这样。 path可以是您需要的任何内容,例如SD卡,URL。

答案 1 :(得分:0)

根据Android developer website

  

在Android 2.3.3(API级别10)及更低版本上,建议使用recycle()。如果您在应用中显示大量位图数据,则可能会遇到OutOfMemoryError错误。 recycle()方法允许应用程序尽快回收内存。

     

警告:只有在确定时才应使用recycle()   不再使用位图。如果您调用recycle()及更高版本   尝试绘制位图,你会得到错误:“画布:试图   使用回收的位图“。

我的建议是检查您要显示的图像数量和每个图像的大小。如果要显示大量图像,则使用像通用图像加载器这样的延迟加载库。我很少使用bitmap.recycle,因为在回收位图后,你再也不能使用它了。