【问题标题】:OutOfMemory - how to prevent [closed]OutOfMemory - 如何防止[关闭]
【发布时间】:2026-01-06 19:40:01
【问题描述】:

我正在寻找解决方案来防止 Android 上出现 OutOfMemory 错误。搜索 OutOfMemory 时的大部分主题是关于我不使用的位图。 我的问题是将大量数据从数据库加载到表单。我需要允许在一个视图(活动)中添加多个表单。但是如果我加载太多数据,我最终会得到 OutOfMemory。我怎样才能防止这种情况?我怎么知道我不应该加载更多数据,因为我会得到 OutOfMemory ?

【问题讨论】:

  • 你的sdk最低版本是多少???

标签: android memory


【解决方案1】:

您可以在ListView 中显示表单,并在用户通过适配器的getView 滚动时动态加载适当的数据。

我怎么知道我不应该加载更多数据,因为我会得到 内存不足?

一般情况下,如果需要加载大量数据,则应根据需要加载,并在未显示或不必要时丢弃,因此您需要在应用程序中确定这些点。

我有这个调试功能,我在分配大量图像时经常使用它。您可以使用它来查看内存何时耗尽,并根据需要对其进行调整以停止分配更多内存。

synchronized private void debugMemoryUsage() {
    DecimalFormat df = new DecimalFormat();
    df.setMaximumFractionDigits(2);
    df.setMinimumFractionDigits(2);
    // Native heap
    Double allocated = Double.valueOf(Debug.getNativeHeapAllocatedSize())/BYTES_PER_MB;
    Double available = Double.valueOf(Debug.getNativeHeapSize())/BYTES_PER_MB;
    Double free = Double.valueOf(Debug.getNativeHeapFreeSize())/BYTES_PER_MB;
    // Runtime 
    Double runtimeTotal = Double.valueOf(Runtime.getRuntime().totalMemory())/BYTES_PER_MB;
    Double runtimeMax = Double.valueOf(Runtime.getRuntime().maxMemory())/BYTES_PER_MB;
    Double runtimeFree = Double.valueOf(Runtime.getRuntime().freeMemory())/BYTES_PER_MB;

    Log.v(Tag.IMAGE_CACHE, "=================================");
    Log.v(Tag.IMAGE_CACHE, "NATIVE HEAP : allocated " + df.format(allocated) + "MB of " + df.format(available) + "MB (" + df.format(free) + "MB free)");
    Log.v(Tag.IMAGE_CACHE, "RUNTIME MEMORY: total : " + df.format(runtimeTotal) + "MB : vm max : " + df.format(runtimeMax)+ "MB : free : " + df.format(runtimeFree) +"MB free");
    Log.v(Tag.IMAGE_CACHE, "*********************************");
}

但根据我的经验,这些数字只是一个估计值,因此您应该保留一个缓冲,因此可能只是分配给 VM 最大值的某个百分比。 VM max 是应用进程可以分配的最大内存,它与手机不同,在旧手机上可以低至 16MB。

【讨论】:

  • 可能是 - 但是我的表单基于 MVC 模式。我需要控制器 - 最占用内存 - 不断加载到内存中,因为它们不是视图的一部分。
  • @light 我不知道你在做什么,但如果你想让它工作,你可能需要打破你正在使用的任何模式并实现你自己的东西。
  • 是的,你说得对,模式应该改变,但是我有特定的任务要做,而且必须这样。但是,没有任何 Android 回调告诉我这样的事情吗?
  • @light 查看我从我的一个项目中发布的代码。
  • 非常有用的功能,谢谢:)如果真的没有Android回调,那就最好了。
【解决方案2】:

由于图像位图尺寸过大而导致内存不足,您可以通过缩小用户查看的图像来减少此问题:check how to scale down

为防止内存崩溃,将位图保存在SoftReference数组中,当超出内存时会自动清除图像而不是崩溃,在读取图像之前检查是否删除然后重新上传位图到内存:

HashMap<String,SoftReference<Bitmap>> caschedImages;

【讨论】: