【发布时间】:2012-05-01 05:03:03
【问题描述】:
我必须相信有一种方法可以在不再需要图像数据时从内存中清除它,但尽管进行了详尽的搜索,我还是找不到解决方案。 stack 和 google android dev list 都充满了关于 OOM 错误的问题,特别是“位图大小超出 VM 预算”,但我仍然没有看到明确的答案。
我了解设备存在硬内存限制,并且我了解加载和显示或缓存大量图像数据是不现实的,但应该避免丢弃不再需要的数据。
例如,想象一下这个非常基本的假设应用程序,它模拟了本地图库应用程序的许多行为:
- 一个允许用户细读来自远程服务器的图像的图库。
- 该服务器上可能有任意数量的图像。
- 该应用一次显示 1 张图像,并允许用户通过按下按钮或滑动来一次后退或前进 1 张图像。
- 任何时候最多可以渲染 3 张图像(因此用户可以在滑动时立即看到当前图像左侧或右侧的图像)。应丢弃所有其他图像数据。
- 使用 URL.openStream 和 Drawable.createFromStream 或 BitmapFactory.decodeStream 加载图像。流已适当关闭。
- 在获取图像之前,在服务器上调整了合适的大小。
- 加载发生在 AsyncTasks 中。不再需要的任务(由于从具有不完整任务的图像中移开)被取消。 AyncTask 中的任何引用都是 WeaklyReferenced。
- 当不再需要任何图像时,它会通过以下方式“清除”:
- getBackground().setCallback(null)
- 监听器设置为空
- setImageDrawable/Bitmap(null)
- 删除视图
这个简单的结构考虑了我所知道的所有建议做法,在某些时候不可避免地会因 OOM 错误而崩溃。使用 BitmapFactory.Options inSampleSize 和 inPreferredConfig 将延迟不可避免的情况,但不会永远延迟,并且会以图像质量为代价。在此示例中,我使用了远程图像,但存储在 /assets/ 或内存等中的图像存在问题。
我的感觉是,如果我们可以在某一点显示 X 数量的图像数据,并且我们采取所有步骤从内存中删除该图像数据,那么以后应该能够显示相同数量的数据,而无需进行补偿对于之前发生的事情。
由于关于这个问题的问题数量众多,我希望有一个标准解决方案记录在案,但如果有的话,我找不到它。我看过 Romain Guy 发布的答案,他在其他方面似乎对他的知识非常慷慨并且在社区中很活跃,他说的是“简单。不要使用太多内存”。好的。告诉我怎么做。
我还应该提到 System.gc 对此没有任何帮助。我也知道 bitmap.recycle,但除非我弄错了,否则不能以这种方式使用它。
我错过了一些基本的东西吗?一旦不再使用图像数据,有没有办法丢弃它?上面缺少什么来创建一个简单的照片库?假设内置画廊应用程序使用框架而不是 NDK,我想必须有一种方法......
TYIA。
/这个问题也已经发布在android开发者google群列表中了。
【问题讨论】:
标签: android