android - 从内存中删除图像数据

标签 android

我必须相信,一旦不再需要图像数据,就有一种方法可以从内存中清除图像数据,但尽管进行了详尽的搜索,我仍找不到解决方案。堆栈和 google android 开发列表都充满了有关 OOM 错误的问题,特别是“位图大小超出 VM 预算”,但我仍然没有看到明确的答案。

我知道设备上存在硬内存限制,并且我知道加载、显示或缓存大量图像数据是不现实的,但应该有办法丢弃不再需要的数据。

例如,想象一下这个非常基本的假设应用程序,它模拟 native 图库应用程序的许多行为:

  1. 允许用户仔细阅读远程服务器上的图像的图像库。
  2. 该服务器上可能有任意数量的图像。
  3. 该应用一次显示 1 张图像,并允许用户通过按下按钮或滑动操作一次后退或前进 1 张图像。
  4. 一次最多渲染 3 个图像(因此用户在滑动时可以看到紧邻当前图像左侧或右侧的图像)。所有其他图像数据都应被丢弃。
  5. 使用 URL.openStream 和 Drawable.createFromStream 或 BitmapFactory.decodeStream 加载图像。流被适当关闭。
  6. 在获取图像之前,在服务器上会调整图像的大小。
  7. 加载发生在 AsyncTasks 中。不再需要的任务(由于远离任务未完成的图像)​​将被取消。 AyncTask 中的任何引用都是 WeaklyReferenced。
  8. 当不再需要任何图像时,它会通过以下方式“清除”:
    • getBackground().setCallback(null)
    • 监听器设置为 null
    • setImageDrawable/Bitmap(null)
    • 删除 View

这个简单的构造考虑了我所知道的所有建议实践,在某些时候将不可避免地因 OOM 错误而崩溃。在SampleSize 和inPreferredConfig 中使用BitmapFactory.Options 会延迟不可避免的情况,但不会永远,并且会以图像质量为代价。在此示例中,我使用了远程图像,但存储在/assets/或内存等中的图像存在问题。

我的感觉是,如果我们可以在某一点显示 X 数量的图像数据,并且我们采取所有步骤从内存中删除该图像数据,那么我们以后应该能够显示相同数量的数据,而无需进行补偿对于之前发生的事情。

由于关于这个问题的问题数量巨大,我希望有一个标准的解决方案记录下来,但如果有的话,我找不到它。我看过 Romain Guy 发布的答案,他在其他方面似乎对自己的知识非常慷慨并且在社区中很活跃,他说“简单。不要使用那么多内存”。好的。告诉我怎么做。

我还应该提到 System.gc 对此没有任何帮助。我也知道 bitmap.recycle,但除非我弄错了,否则不能以这种方式使用。

我是否遗漏了一些基本的东西?有没有办法在不再使用图像数据后将其丢弃?上面创建一个简单的照片库还缺少什么?假设内置图库应用程序使用框架而不是 NDK,我想必须有一种方法......

TYIA。

/这个问题也已发布在 Android 开发者 Google 群组列表中。

最佳答案

通过我与 Prime 的合作我发现了一些提示,其中之一您没有提到。解码位图时,请确保在 BitmapFactory.Options 中使用 inPurgeableinInputShareable 标志。这会有一点帮助,但我建议您看看我在 Prime 中实现的图像加载。我在所有产品中都使用它,没有任何内存问题。我发现 95% 的内存问题都是由于 Bitmap 类的错误使用造成的。

关于android - 从内存中删除图像数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10389524/

相关文章:

Android API 21 创建自定义主 key

android - Firestore 并发连接是否限制为 1M?

android - 无法从函数 serviceAdded 中的 ServiceEvent 获取 txtrecords(来自 JmDNS)

android - 如何在 Android 11 上启动ActivityForResult?

android - .APK 上传失败

java - setText 未出现/更新

android - 无法录制音频

android - 将应用程序与 Google 搜索结果和 Chrome 集成

android - Webview 重新加载蜂窝中的方向变化

java - 谷歌地图聚类不适用于少量坐标