【问题标题】:GC is too active on BitmapFactory.decodeStream()GC 在 BitmapFactory.decodeStream() 上过于活跃
【发布时间】:2015-09-21 17:44:31
【问题描述】:

我有一个显示缩略图网格的应用程序。该应用程序将输入流解码为带有BitmapFactory.decodeStream() 的位图,以便显示每个缩略图。

我注意到当我向上/向下滚动的速度足够快时,如果 GC 超级活跃,这会使滚动变得生涩。



我试图隔离问题并编写了一个简单的应用程序,我在其中循环执行 10000 次 decodeStream() 调用,并注意到即使有足够的内存,GC 仍然会不断触发(即使我调用 bitmap.recycle()每次迭代后)。

问题:如何防止GC在执行BitmapFactory.decodeStream()时过于活跃?

【问题讨论】:

  • 通常,缩略图的大小都相同,或者至少来自少数几个大小之一。在这种情况下,请在 BitmapFactory.Options 上使用 inBitmap 以重用 Bitmap 对象,而不是回收它们。
  • inBitmap 工作得非常好,GC 几乎闲置了。我正在测试 4.4.4。它是否会在 Android >=5.0 上提供相同的提升,或者对 L 进行的优化使得 inBitmap 的使用变得不必要(不值得增加复杂性)?

标签: java android bitmap garbage-collection bitmapfactory


【解决方案1】:

在 Android 中处理内存的一般方法与环境问题的口头禅相同:减少、重用、回收。 “减少”意味着“减少请求”(例如,在 BitmapFactory.Options 上使用 inSampleSize 仅加载下采样图像)。 “回收”的意思是“确保它可以尽快被垃圾回收”。

但是,在“回收”之前是“重用”。 The Dalvik garbage collector is not a compacting or moving collector, so heap can become fragmented。如果您已经有一个正确大小的分配,请重复使用它,而不是让它被收集然后必须再次重新分配它。对于位图,这意味着在 BitmapFactory.Options 上使用 inBitmap,或者使用为您执行此操作的图像加载库。

它会在 Android 上提供同样的提升吗>=5.0

通常是的,但具体影响可能会有所不同。

或者对 L 进行的优化使得 inBitmap 的使用没有必要(不值得增加复杂性)?

ART 的垃圾收集器有多种改进。最重要的是它一个压缩或移动收集器,尽管只有当你的应用程序在后台时,这对你的情况没有多大帮助。

但是,ART 也有一个单独的堆区域用于大字节数组(或其他没有指向其中其他对象的指针的大型对象)。 ART 收集这些的效率要高得多,而且它们会减少堆碎片。

话虽如此,我还是会使用inBitmap。如果您的 minSdkVersion 是 21 岁以上,也许您可以尝试跳过 inBitmap,看看情况如何。但是,如果您的minSdkVersion 低于 21,则无论如何您都需要inBitmap,我会全面使用该代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-12
    • 2012-10-02
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 2019-08-30
    相关资源
    最近更新 更多