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

问题描述:

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

@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缓存(应用程序崩溃,因为内存不足)时应用程序是否会释放内存问题?

  • 只有一个LRU缓存可用于整个应用程序吗?

  • 整个应用程序有多个LRU缓存,它们会成为问题吗?

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

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

的LRU缓存将不会自动释放内存的应用程序将有问题来释放内存。您需要以编程方式驱逐条目。

只有一个LRU缓存整个应用程序,它可以是一个问题?

整个应用程序有多个LRU缓存,它们会成为问题吗?

LruCache类是一个泛型类,其中包含键的类型和值的类型。我想说你想要为每个要缓存的对象类型创建一个LRU缓存。你正在做我所做的事:缓存Bitmap s和键入String s。

只是旁注:小心使用bitmap.getByteCount()。 JavaDocs说:

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

我正在使用LRU Cache作为Bitmap s。我认为只要调用此方法就可以覆盖Application.onTrimMemory()并清除缓存。

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

但在这里会发生什么:当我的应用程序在内存不足的状态,我的应用程序会尝试下载与内存不足的图像时,GC将运行,但BitmapFactory仍然无法为Bitmap分配内存。日志显示onTrimMemory()方法异步调用,有时在投掷OutOfMemoryError后几乎整整一秒!

HEY GOOGLE:如果系统不能告诉我,我的内存不足UNTIL OutOfMemoryError被抛出后,如何在地狱我应该怎么管理我的记忆?

疯狂。纯粹,完全疯狂。

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

所以在你实现你的LRU缓存之后,确保你压力测试你的应用程序;尝试将其纳入低内存环境并查看其行为。对我来说,使用模拟器时效果最好。该模拟器将具有96M的小堆限制,但如果它具有高屏幕分辨率,则图像资源将会变得非常大,这使得内存最大化变得相当容易。

如果要显示缩略图,但你从服务器获取图像,他们可能比你的大ImageView,请确保你阅读这篇文章:Loading Large Bitmaps Efficiently | Android Developers学习如何下载一个适当大小的位图,不浪费内存。

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

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

并准备处理一点挫败感。

+0

嗨!此时我正在初始化listview构造函数中的weakHashMap,并将缩略图放在该地图中。我当时认为最好使用LRU缓存,但在阅读你的答案后,我有点害怕。 – aeroxr1

+1

我刚才看了一下'WeakHashMap'。我没有意识到这是*键*在该类中具有弱引用,而不是值。出于这个原因,我想你可能想要像'Map >'这样的地图。我现在有点希望,我已经这样做了。由于'LruCache'类与GC没有任何隐含关系,因此几乎没有用处。所以你可能走在正确的轨道上。只要测试它的废话,如果它的行为可以接受,宣布胜利,并称它为一天。 –

+0

在弱哈希图是弱关键的参考?真的吗?我不知道这个! – aeroxr1