LRU缓存:只为整个应用初始化一个?

时间:2016-09-16 20:19:33

标签: android performance listview caching android-lru-cache

在我的应用中,我有不同的列表视图,其中包含一些缩略图。 今天我开始重构,我想实现LRU缓存。我遵循Android指南,但我想知道是否更好地初始化整个应用程序的一个LRU缓存,或者更好地为每个列表视图初始化LRU缓存。 我害怕outOfMemory。 因此,我有以下问题,我无法自己回答:   - 用singleton模式初始化的一个LRU缓存是个好主意?   - 如果内存不足,是否会导致outOfMemory情况下LRU Cache的初始化?

 @Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get max available VM memory, exceeding this amount will throw an
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an
    // int in its constructor.
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);

    // Use 1/8th of the available memory for this memory cache.
    final int cacheSize = maxMemory / 8;

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in kilobytes rather than
            // number of items.
            return bitmap.getByteCount() / 1024;
        }
    };
    ...
}
  • 如果内存不足,LRU缓存会自动释放吗?我想知道当我使用LRU Cache时应用程序是否有释放内存的问题(应用程序崩溃,因为内存不足?)

  • 整个应用只有一个LRU缓存,这可能是个问题吗?

  • 整个应用程序有多个LRU缓存,这可能是个问题吗?

1 个答案:

答案 0 :(得分:1)

我遇到了很多问题,所以我可以在这里给你一些有用的答案。

  

如果内存不足,LRU缓存会自动释放吗?我想知道如果我使用LRU Cache

,应用程序是否会有释放内存的问题

LRU Cache将自动释放内存。您需要以编程方式逐出条目。

  

整个应用只有一个LRU缓存,这可能是个问题吗?

     

整个应用程序的多个LRU缓存,它们可能是个问题吗?

LruCache类是一个泛型类,其中包含键的类型和值的类型。我想说你想为你正在缓存的每个对象类型都有一个LRU Cache。您正在做我做的事情:缓存Bitmap并使用String进行键入。

请注意:使用bitmap.getByteCount()时要小心。 JavaDocs说:

  

从KITKAT开始,此方法的结果不再用于确定位图的内存使用情况。请参阅getAllocationByteCount()

我正在为Bitmap使用LRU缓存。我认为只要调用此方法,覆盖Application.onTrimMemory()并清除缓存就足够了。

另外,我做了同样的事情,并根据应用程序可用的堆内存百分比设置了缓存大小。

但是接下来会发生什么:当我的应用程序处于内存不足状态且我的应用程序尝试下载内存不足的图像时,GC会运行,但BitmapFactory仍然无法分配内存Bitmap。日志显示onTrimMemory()方法被异步调用 ,有时在OutOfMemoryError被抛出后几乎整整一秒!

HEY GOOGLE:如果系统无法告诉我,我的内存很低,直到 AFTER OutOfMemoryError后, 如何在地狱中我支持管理我的记忆?

精神错乱。纯粹的疯狂。

以下是我最终要做的事情:我将在try块中捕获OutOfMemoryError,清除那里的缓存,然后重试图像请求到服务器。他们告诉你不要做的确切事情。但它最终解决了我的问题。该应用程序现在更加稳定。

因此,在实施LRU Cache之后,请确保对应用程序进行压力测试;尝试将其置于低内存状态并查看其行为方式。对我来说,使用模拟器时效果最好。模拟器有一个96M的小堆限制,但是如果它的屏幕分辨率很高,那么图像资源可以扩展到相当大,这使得将内存推到最大程度非常容易。

如果您正在显示缩略图,但是您从服务器获取图像并且它们可能比ImageView更大,请务必阅读本文:Loading Large Bitmaps Efficiently | Android Developers以了解如何下载位图的位图适当的大小而不浪费记忆。

您也可以尝试让系统执行缓存并设置HttpResponseCache

无论你最终做什么,一定要强调你的应用程序,看看当没有多少堆剩余时它的行为。

并准备应对一点挫折。