什么时候应该使用 LRUCache 回收位图? [英] When should I recycle a bitmap using LRUCache?

查看:14
本文介绍了什么时候应该使用 LRUCache 回收位图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 LRUCache 来缓存存储在文件系统上的位图.我根据此处的示例构建了缓存:http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

I'm using an LRUCache to cache bitmaps which are stored on the file system. I built the cache based on the examples here: http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

问题是我在使用该应用程序时发现 OutOfMemory 经常崩溃.我相信当 LRUCache 驱逐一个图像为另一个图像腾出空间时,内存不会被释放.

The problem is that I'm seeing OutOfMemory crashes frequently while using the app. I believe that when the LRUCache evicts an image to make room for another one, the memory is not being freed.

当图像被驱逐时,我添加了对 Bitmap.recycle() 的调用:

I added a call to Bitmap.recycle() when an image is evicted:

  // use 1/8 of the available memory for this memory cache
    final int cacheSize = 1024 * 1024 * memClass / 8;
                mImageCache = new LruCache<String, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return bitmap.getByteCount();
                }

                @Override
                protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) {
                    oldBitmap.recycle();
                    oldBitmap = null;
                }
            };

这修复了崩溃,但它也会导致图像有时没有出现在应用程序中(只是图像应该出现的黑色空间).任何时候我都会在 Logcat 中看到此消息:无法从位图生成纹理.

This fixes the crashes, however it also results in images sometimes not appearing in the app (just a black space where the image should be). Any time that occurs I see this message in my Logcat: Cannot generate texture from bitmap.

快速谷歌搜索显示这是因为显示的图像已被回收.

A quick google search reveals that this is happening because the image which is displaying has been recycled.

那么这里发生了什么?如果我只是在它们被删除后回收它们,为什么回收的图像仍然在 LRUCache 中?实现缓存的替代方法是什么?Android 文档明确指出 LRUCache 是要走的路,但他们没有提到需要回收位图或如何这样做.

So what is happening here? Why are recycled images still in the LRUCache if I'm only recycling them after they've been removed? What is the alternative for implementing a cache? The Android docs clearly state that LRUCache is the way to go, but they do not mention the need to recycle bitmaps or how to do so.

已解决:如果它对其他人有用,那么已接受的答案所建议的解决此问题的方法是 NOT 执行我在上面的代码示例中所做的操作(不要回收 中的位图entryRemoved() 调用).

RESOLVED: In case its useful to anyone else, the solution to this problem as suggested by the accepted answer is to NOT do what I did in the code example above (don't recycle the bitmaps in the entryRemoved() call).

相反,当您使用完 ImageView(例如活动中的 onPause(),或者在适配器中回收视图时)检查位图是否仍在缓存中(我在缓存类中添加了一个 isImageInCache() 方法),如果不是,则回收位图.否则,别管它.这修复了我的 OutOfMemory 异常并阻止回收仍在使用的位图.

Instead, when you're finished with an ImageView (such as onPause() in an activity, or when a view is recycled in an adapter) check if the bitmap is still in the cache (I added a isImageInCache() method to my cache class) and, if it's not, then recycle the bitmap. Otherwise, leave it alone. This fixed my OutOfMemory exceptions and prevented recycling bitmaps which were still being used.

推荐答案

我相信当 LRUCache 驱逐一个图像为另一个图像腾出空间时,内存并没有被释放.

I believe that when the LRUCache evicts an image to make room for another one, the memory is not being freed.

它不会,直到 Bitmap 被回收或垃圾收集.

It won't be, until the Bitmap is recycled or garbage-collected.

快速谷歌搜索显示这是因为显示的图像已被回收.

A quick google search reveals that this is happening because the image which is displaying has been recycled.

这就是为什么你不应该在那里回收.

Which is why you should not be recycling there.

如果我只是在它们被删除后回收它们,为什么回收的图像仍然在 LRUCache 中?

Why are recycled images still in the LRUCache if I'm only recycling them after they've been removed?

据推测,它们不在 LRUCache 中.它们位于 ImageView 或其他仍在使用 Bitmap 的东西中.

Presumably, they are not in the LRUCache. They are in an ImageView or something else that is still using the Bitmap.

实现缓存的替代方法是什么?

What is the alternative for implementing a cache?

为了便于论证,我们假设您在 ImageView 小部件中使用 Bitmap 对象,例如在 ListView 的行中.

For the sake of argument, let's assume you are using the Bitmap objects in ImageView widgets, such as in rows of a ListView.

当您完成一个 Bitmap(例如,ListView 中的行被回收),您检查它是否仍在缓存中.如果是,你就别管它了.如果不是,你recycle()它.

When you are done with a Bitmap (e.g., row in a ListView is recycled), you check to see if it is still in the cache. If it is, you leave it alone. If it is not, you recycle() it.

缓存只是让您知道哪些Bitmap 对象值得保留.缓存无法知道 Bitmap 是否仍在某处使用.

The cache is simply letting you know which Bitmap objects are worth holding onto. The cache has no way of knowing if the Bitmap is still being used somewhere.

顺便说一句,如果您使用的是 API 级别 11+,请考虑使用 inBitmap.OutOMemoryErrors 在分配无法完成时触发.最后我检查了一下,Android 没有压缩垃圾收集器,因此您可能会由于碎片(想要分配比最大的单个可用块更大的块)而得到 OutOfMemoryError.

BTW, if you are on API Level 11+, consider using inBitmap. OutOMemoryErrors are triggered when an allocation cannot be fulfilled. Last I checked, Android does not have a compacting garbage collector, so you can get an OutOfMemoryError due to fragmentation (want to allocate something bigger than the biggest single available block).

这篇关于什么时候应该使用 LRUCache 回收位图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆