android - 在处理位图时调用 System.gc() 和 Thread.sleep() 是否有意义?

标签 android bitmap garbage-collection

我跳到了Android项目,它分配了很多Bitmaps。我在那里遇到了这段代码:

  System.gc();
  try {
    b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  } catch (OutOfMemoryError e) {
    System.gc();
    try {
      Thread.sleep(100);
    } catch (InterruptedException e1) {
      log.error("Failed to sleep.");
    }
    try {
      b = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
    } catch (OutOfMemoryError e1) {
      log.error("Error", e1);
    }
  }

我开始想知道在调用 System.gc() 后让线程休眠一段时间是否有任何意义? 我自己对 System.gc() 做了一些研究,发现了一些关于它如何工作的信息:

Patrick Dubroy据说在 Android >= Honeycomb 上垃圾收集大约需要 5ms(已优化且并发)。

此外,在一些地方我发现了信息,调用 System.gc() 只是运行垃圾收集器的建议。上面的代码是过去两年增强的项目的一部分,我认为这个 Thread.sleep 是针对此时出现的问题的一些解决方法。

有什么想法吗?

最佳答案

看起来 Thread.Sleep() 被调用,以便在发生 OutOfMemoryError< 时尝试重新创建 Bitmap 之前为垃圾收集器提供足够的时间来完成其工作 第一次尝试时就发生了。第二次尝试时,使用较低的标准来消耗更少的内存:RGB_565 而不是 ARGB_8888

在第一次尝试创建Bitmap之前测试可用内存量会更好(对于并发应用程序来说更高效/更容易读取/更强/更少危险),而不是捕获内存不足错误

Thread.sleep(100) 则假设垃圾收集将启动并在 100 毫秒内完成,这绝对是任意的。它可能还没有开始,可能仍在运行......

无论如何,调用 System.gc() 在这里没有帮助,因为垃圾无论如何都会被收集。虚拟机会检测到这一点,并且如果有大量垃圾需要收集,则不会等待。

所以我的建议是:

  • 忘记这些 System.gc()Thread.Sleep() 调用。他们效率低下/乐于助人。
  • 在首次尝试创建位图之前测试可用内存量。您可以确定 future 生成的位图的大小,因为您知道它的大小和编码。 (引用: RuntimeActivityManager )
  • 如果剩余内存量较低,如果生成的位图适合(16 位 RGB 而不是 32 位 ARGB),为什么不降低标准。
  • 如果这还不够,记录错误和/或显示警报(取决于您的应用,我不知道上下文)就可以了。

Android 团队的两篇有趣的相关文章:

关于android - 在处理位图时调用 System.gc() 和 Thread.sleep() 是否有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23673642/

相关文章:

WPF 之上的 C# async/await Task<BitmaptImage> 问题

android - 从不起作用的位图中创建或剪切 6 个相等的部分

android - 在 Android 中显示连续图像

c# - .net List<T> 修剪多余的部分

c - 在 C 中使用简单引用计数器的示例代码或项目

用于测试 SQLite 架构更新的 Android ADB

java - ListView 中的android linkify

android - 在 WebView 中隐藏滚动条

c - 垃圾收集器和双重分配的内存

android - fragment 标题中的 ViewPager 图像