【发布时间】:2012-01-07 08:04:12
【问题描述】:
我收到“java.lang.OutOfMemoryError:位图大小超过 VM 预算”错误...我正在做的是从服务器下载大约 50 个图像并将它们存储在内存中。
当我第一次看到这个问题时,我优化了我们的图像以仅下载缩略图(50 个 JPEGS,每个 ~12kB,大小 160x240 像素),并在我不需要它们时通过调用 Bitmap.recycle() 开始释放它们。一切都在较新的手机上运行,该过程可以获得 32MB,但在最大 16MB 的旧手机上不行。
所以我的问题是:
在旧手机上所有进程限制为 32MB 或更少是否正确(即 Runtime.getRuntime().maxMemory() 调用返回的内存)并且此内存用于Dalvik、框架、应用程序和数据?
我们能否在应用程序中使用比 Runtime.getRuntime().maxMemory() 返回的内存更多的内存?
我应该如何优化图像 - 它们现在已经很小了...我应该开始将它们交换到内部闪存/SD 吗?只要它们显示在 GridView...
中,我就会将它们保存在内存中
感谢您的帮助 - 我在这里完成了类似的线程并完成了我在那里看到的......但这仍然不够......
编辑更新
我在weakwire 回答之后添加了这些 cmets。
• 在我的例子中,我下载了大约 50 个图像并将它们全部存储在内存中的位图对象中。请看下面我为什么这样做。
• Bitmap 对象中的图像占用多少内存?是否存在原始格式意味着如果图像是160x240x24bpp,它在内存中占用~115 kB,那么50 images are ~6MB? 正确吗?
• 我还读到图像不是我的进程堆的一部分,但它们被计算在内,因此使用 maxMemory()、totalMemory()、freeMemory() 并没有真正的帮助。 正确吗?
• 我的应用程序 UI 具有完整的自定义图形(60 个 png 文件,其中许多是 draw9pacth 格式)
• 我在 24/32 MB 设备上没有问题,我只有在 16 MB 设备上遇到问题
• 当我下载所有 50 张图像并将它们存储到内存中时,我会以 2 列宽度 GridView 显示它们。我认为为此我需要将所有图像保留在堆上(保存到内部闪存我认为不是解决方案)。 这是正确的假设吗?
• 当我初始化应用程序并加载 UI 时,我可以看到在整个 16384kB 预算中分配了 5459kB 的 448kB 空闲内存。我假设我不能真正使用整个 16384kB + 如果我理解正确我无法从 maxMemory()、totalMemory()、freeMemory() 中真正看到已经加载的图像占用了多少,因为 dalvik-vm 没有“看到”这个堆。假设已经使用了 ~2M,我最多可以使用 ~14MB,我还剩下 5.5MB,所以我很容易在内存中有 50 张图像时遇到 OOM 问题……计算正确吗? p>
我一定会仔细阅读建议的视频 - 看起来不错 - 但weakwire,请尝试回答我的问题......谢谢你的时间!
【问题讨论】:
标签: android