问题:app中有一个Activity用于查看大图,最近出现了一些超大图(内存占用超100M),导致app出现OOM导致的crash
背景:大图的来源中只给出了图片的url,除此之外再无任何信息。图片url提供方对于提供图片其他信息(如宽/高),成本较高,讨论之后有客户端自己进行处理。
1⃣️OOM产生的原因
内存占用量超过了vm能分配的最大内存量,或者一下子申请了一块非常大的内存(比如100M),虽然内存还有很大空间,但是无法一下腾出连续的一片内存进行分配,可能会导致内存溢出。
之前试了一下try-catch,发现是catch不住这种Error的,知乎上一篇回答安卓编程:可否用try-catch捕获Out Of Memory Error以避免其发生?说,try-catch只能catch住在try里面申请内存的变量抛出的Error,而且这次catch住了,下次还是会抛,所以用try-catch解决OOM的问题是不太可行的。
关于vm能分配的内存,android dalvik heap 浅析 这篇文章介绍的非常形象
(1) dalvik.vm.heapstartsize 初始分配的堆size
(2) dalvik.vm.heapgrowthlimit 受控app的极限堆size
(3) dalvik.vm.heapsize 不受控app的极限堆size
这三个值在不同手机上会有所不同,在build.prop文件里,可以查看 Android系统移植与调试之------->build.prop文件详细赏析
dalvik.vm.heapstartsize=5m #单个应用程序分配的初始内存
dalvik.vm.heapgrowthlimit=48m #单个应用程序最大内存限制,超过将被Kill,这或许是某些大体积程序闪退的原因
dalvik.vm.heapsize=256m #dalvik的虚拟内存大小
我们可以通过在manifest中配置android:largeheap=true,可以让app申请的内存达到heapsize,这样app可用内存可以变多。但是这样相应的后果是每次gc的时间也会变长,导致性能变差,我们尽量要从“减少使用的内存”方向优化,避免占用更大的内存。
2⃣️图片占用内存的计算方式
图片占用的字节数 = 图片宽度(像素)* 图片高度(像素)* 单位像素占用字节数
其中图片的宽/高,glide在RequestListener的onSourceReady回调的GlideDrawable中,可以通过GlideDrawable.getIntrinsicWidth()和GlideDrawable.getIntrinsicHeight()获取,单位像素占用字节数根据ARGB方式进行计算,如config为Bitmap.Config.RGB_565表示:每个像素占16位,没有透明度,R-5,G-6&#