安卓缓存:内部存储 vs. 对象缓存

6
我需要缓存来自网络的图像(仅限5个或最多100个),并在列表视图中显示。如果用户选择列表视图的一行,则可以清除缓存。我查看了一些示例。一些使用外部存储,一些使用内部和外部,还有一些对象...
那么,使用内部存储(通过getCacheDir() http://developer.android.com/guide/topics/data/data-storage.html#filesInternal)和对象缓存(类似于WeakHashMap或HashMap >)有哪些优缺点?
软引用的问题似乎是它们可能会被过早地回收(SoftReference gets garbage collected too early)。那么Android内部存储怎么样?参考说:“这些文件将是设备存储空间不足时首先删除的文件。”
使用对象缓存或临时内部存储是否有任何区别?除了对象缓存应该会更快一些。
2个回答

10
以下是两者之间的几个区别:
  • 对象缓存比内部存储快,但容量较低。
  • 对象缓存是短暂的,而内部存储具有更长的寿命
  • 对象缓存占用堆中的实际空间,而内部存储不占用。这是一个重要的点,因为使对象缓存过大可能会导致OutOfMemoryException即使使用SoftReference也一样

鉴于这些差异,它们并非完全相互排斥。我们实现了许多使用多层缓存特别是涉及图像加载的东西。以下是我们使用的步骤:

  • 如果尚未缓存图像,则从URL获取并在第一级缓存中(即SoftReference/WeakHashMap或使用有限大小的LinkedHashMap的硬缓存)进行缓存。
  • 然后,在LinkedHashMap中实现removeEldestEntry()。一旦达到硬缓存容量,我们将内容移至二级缓存,即内部存储。使用此方法,您无需重新从URL获取图像+仍然更快,并且可以释放内存。
  • 我们会定期在后台对内部存储运行LRU算法的清理。您不应该依赖Android来为您清除此内容。

我们已将多层缓存制作为通用组件,并在许多客户项目中使用它。此技术几乎与计算机架构中的L1、L2缓存相同。


+1 它们肯定不是互相排斥的!你需要两者,这是一个很好的方法。 - David Snabel-Caunt
2
好的建议。对于对象缓存,您可以使用此处找到的LruCache解决SoftReference问题,而且不必太担心实现:http://developer.android.com/reference/android/util/LruCache.html,同时也可以在兼容性库中找到。 - kabuko
又有一个问题。如何确定链表的大小/限制(10个、50个或100个对象)?我想应该取决于要存储的对象的大小。 - 207
@207 是的,没错。我将它作为公共组件的参数来创建,这样我就可以针对我们开发的每个应用程序进行定制。 - momo
如何确定限制?例如,假设最坏情况下我想缓存多达1000个位图。每个位图大约50kb。确定第一级缓存(例如LinkedHashMap)的限制的方法是什么? - 207
大部分都是有根据的猜测。我们通常通过运行dumpsys meminfo并观察应用程序内存消耗来进行分析,使用一些基于我们过去遇到的不同数字。这些数据成为我们决定哪个数字最好操作的依据。我们还发现,在许多测试手机中,将第一级缓存设置为较低的数字并将它们存储在内部存储器中并不会对性能产生太大影响。根据您的应用程序,保守地将第一级缓存设置为较低的数字可能仍然有效。 - momo

0

这是我获取示例的地方。有些使用内部,有些使用外部,还有一些使用对象。这与懒加载有关,而不是存储。 - 207

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