OOM,即OutOfMemory。作为Android设备常见的性能问题,经常见于图片大量加载的场景。然而博主这次碰到的OOM,却是由一个意想不到又合情合理的问题导致。由于是半路接手一个正在开发的项目,着实被坑了一把。
一. 场景描述:
-
在一个Activity中,会异步生成一张二维码图片。不过这个功能显然是后来匆忙加的,因为二维码Bitmap并没有缓存(项目其它地方的图片都是用Glide)。这样导致每次进入Activity,都会重新创建一个Bitmap。
-
在使用App较长时间后,再次进入这个Activity偶尔会导致OOM。
二. 尝试解决
-
这个二维码Bitmap,像素为700*700.我们尝试使用Glide加载到ImageView中,这样只会在第一次进入Activity时,才会通过ZXing创建二维码Bitmap。
不过在经过测试之后,仍然会出现OOM。我们打开Android Profiler,来监测内存情况:
-
对比进入Activity前后的内存占用情况:
Graphics的内存占用突然增长了51M。
而且是每次进入Activity,都会发生如此剧烈的抖动,除了二维码图片,还有其它的问题。
-
注释掉二维码图片的生成,然后再次观察测试。情况依旧,内存占用峰值瞬时增加50-100M:
三. 大家来找茬
-
疑点:
在有点懵圈的时刻,不经意间瞟了一眼界面,发现了可疑之处:
开始看见这块白色背景时,还以为是设置了color;
切到相关布局xml一看:
android:background="@drawable/layout_bg"
很好,去目录下看看这张图:
简直吓死宝宝了,一张1034*1398的无码高清PNG大图…
-
再次尝试:
android:background="#ffffff"
顺滑多了:
至此问题解决,罪魁祸首就是那一张高分辨率无码高清大图。
四. 小结
- Android Profiler是好工具。
- 任何图片的加载,都会出现增加内存开销。图片缓存的意义也就在于此-----通过缓存策略控制图片的内存消耗。然而直接在XML中设置加载图片,就没办法使用缓存了。
- 本来这个问题应该很容易发现的,但半路接手项目,还不太熟悉,以至于走了弯路。当然,那张二维码图片仍然是应当缓存起来的。
- 要跟产品、美工沟通好,这种神奇的背景图片就不应当用,它会拖慢加载速度,增加内存压力。而且还有更好的处理方式。比如9Patch,VectorDrawable,等等。