我已经跳转到Android项目,该项目分配了大量的位图。我在那里遇到了这段代码:
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()之后暂停Thread一段时间是否有任何意义? 我自己做了一些关于System.gc()的研究,我发现它的工作原理很少:
Patrick Dubroy表示Android上的垃圾收集> = Honeycomb需要大约5毫秒(它已经过优化和并发)。
此外,在很少的地方我找到了信息,调用System.gc()只是一个运行垃圾收集器的建议。上面的代码是项目的一部分,在过去的两年里得到了增强,我想这个Thread.sleep是针对此时出现的问题的一些解决方法。
有什么想法吗?
答案 0 :(得分:3)
看起来Thread.Sleep()
被调用,为垃圾收集器提供足够的时间来完成其工作,如果在第一次尝试时发生Bitmap
,则尝试重新创建OutOfMemoryError
。在第二次尝试时,使用较低的标准来消耗较少的内存:RGB_565
而不是ARGB_8888
。
在第一次尝试创建Bitmap
之前测试可用内存量会更好(更高效/更容易读取/更强/更低危险并发应用程序),而不是捕获{{1 }}。
OutOfMemoryError
,就其本身而言,假定垃圾收集将在100毫秒内完成并完成,这绝对是任意的。它可能尚未开始,它可能仍在运行......
无论如何,调用Thread.sleep(100)
在这里没有用,因为无论如何都会收集垃圾。如果有大量垃圾需要收集,VM会检测到并且不会等待。
所以我的建议是:
System.gc()
和System.gc()
来电。他们没有效率/乐于助人。Thread.Sleep()
之前测试可用内存量。您可以确定未来的大小Bitmap
,因为您知道它的大小和编码。 (参考:Runtime和ActivityManager)Bitmap
适合(16位RGB而不是32位ARGB)。Android团队的两篇有趣的相关文章:
答案 1 :(得分:1)
谢谢Shlublu提示可以解决什么问题:)我已经决定减少Thread.sleep两次 - 50ms就足够了。此外,我只在开始时调用System.gc(),因为从我看到的情况来看,当createBitmap
失败时没有分配内存 - 所以每次发生OOMException时调用Garbage Collector都没有意义。这是我最终得到的代码。从特征的角度来看,它只是一种重构,但也许对某人有用。
public static Bitmap allocateBitmap(int width, int height) {
Bitmap bitmap = null;
System.gc();
try {
Thread.sleep(50);
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError e8888) {
// error log
try {
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
} catch (OutOfMemoryError e565) {
// error log
}
} catch (InterruptedException e) {
log.error("Failed to sleep", e);
} finally {
return bitmap;
}
}