我在这里阅读了When should I recycle a bitmap using LRU Cache和其他几个问题,我仍然在努力解决OutOfMemoryExceptions问题。但我已经领先于自己了。
我正在接管一个显示大量图片的应用。主要是使用子类ArrayAdapter在网格视图中完成。使用异步任务从Web上加载图像,并将其存储在缓存中(我最终将切换到LRU缓存)。
网格视图中的每张图片都可以显示图像的详细视图(包含更多详细信息/ UI组件),这可能会导致另一个网格视图。最终堆栈上有太多的视图,我们的内存耗尽。缓存正在通过Application.onLowMemory()
函数完全刷新图像,但尽管如此,我们的内存已经不足。
在回收视图时,适配器永远不会检查缓存中是否有任何内容,我确信这可能会给我带来一些喘息的空间,但感觉回收图像在活动中会有很大的好处。堆叠中有4层以上的层。问题是,我不知道如何实现这一目标。在onPause
例程中?
似乎在onPause
例程运行时(切换到下一个Activity层),它显示的图像仍然在缓存中,因此它们不会被回收。我是否需要拉出活动堆栈并在此时调用旧活动上的一些自定义例程来告诉他们回收图像?
此外,我正在尝试支持API级别9-19。 LRU缓存是通过支持库为低级API提供的,在API 12中添加了全功能的,但显然如果我使用支持版本,任何运行API 12+的设备都不会使用更新的版本 - 我应该是编写自定义代码来检测API版本,然后使用某种LRUCache工厂来创建我需要的版本?我是否需要编写自定义代码才能在低于11的API上进行位图回收?
答案 0 :(得分:2)
我最终采用的解决方案是:
我添加了支持LRU Cache,然后还添加了Jake Wharton的DiskLRU Cache。在从Web下载图像之前,首先检查内存LRUCache,然后检查DiskLRUCache。下载的任何图像都存储在两者中。接下来,拥有任何映像的每个Fragment和Activity都被注册为LRU Cache的侦听器。如果LRU Cache要驱逐图像以为另一个图像腾出空间,它会向所有收听的片段和活动发送通知。然后,这些侦听器将其图像标记为“脏”,这意味着需要重新下载它们,然后在位图上调用recycle()
。
这种方法似乎总体上运作良好。该应用程序仍然可能陷入垃圾收集困境,并且很长一段时间后仍然可能在旧手机上耗尽内存,但很难看到我可以在哪里进一步改进它。