0

我已经阅读了何时应该使用 LRU 缓存和其他几个问题回收位图,并且仍在与 OutOfMemoryExceptions 作斗争。但我正在超越自己。

我正在接管一个显示大量图像的应用程序。这主要是在网格视图中使用子类 ArrayAdapter 完成的。使用异步任务从 Web 加载图像,并存储在缓存中(我最终将切换到 LRU 缓存)。

网格视图中的每张图片都可以导致图像的详细视图(带有更多细节/UI 组件),这可以导致另一个网格视图。最终,堆栈上的视图太多,以至于我们的内存不足。缓存正在通过该Application.onLowMemory()函数完全刷新图像,但尽管如此,我们的内存不足。

适配器在回收视图时从不检查缓存中是否有任何内容,我相信这可以给我一点喘息的空间,但感觉最大的收获是在 4+ 的活动中回收图像层回到堆栈中。问题是,我不确定如何做到这一点。在onPause日常?

似乎当onPause例程运行时(切换到下一个 Activity 层),它显示的图像仍将在缓存中,因此它们不会被回收。我是否需要拉起 Activity 堆栈并在那时对旧的 Activity 调用一些自定义例程来告诉他们回收图像?

此外,我正在尝试支持 API 级别 9-19。LRU 缓存是通过较低 API 的支持库提供的,API 12 中添加了全功能缓存,但显然如果我使用支持版本,任何运行 API 12+ 的设备都不会使用更新版本 - 我应该编写自定义代码来检测 API 版本,然后使用某种 LRUCache 工厂来创建我需要的版本?我是否需要编写自定义代码才能仅对低于 11 的 API 进行位图回收?

4

1 回答 1

2

我最终采用的解决方案是:

我添加了支持 LRU Cache,然后还添加了 Jake Wharton 的 DiskLRU Cache。在从网上下载图像之前,我首先检查了内存 LRUCache,然后是 DiskLRUCache。下载的任何图像都存储在两者中。接下来,拥有任何图像的每个 Fragment 和 Activity 都注册为 LRU 缓存的侦听器。如果 LRU 缓存要驱逐一个图像为另一个图像腾出空间,它会向所有正在侦听的片段和活动发送通知。然后这些听众将他们的图像标记为“脏”,这意味着他们需要重新下载,然后再调用recycle()在位图上。这种方法总体上看起来效果很好。该应用程序仍然可能陷入垃圾收集的困境,并且最终在很长一段时间后仍然可能在旧手机上耗尽内存,但很难看出我可以在哪里进一步改进它。

于 2014-01-03T17:02:36.537 回答