我尽量不打错别字,用词准确,不造成阅读障碍。

今天看到一篇介绍图片在Android中的内存占用的计算方式的文章,感觉写的很棒,就是看的时候总要回翻,感觉还有一些表述上的瑕疵。特在此总结一下,原文在下面:
https://www.jianshu.com/p/3c5ac5fdb62a 总结下来应该是这样的:

一.不使用第三方框架加载图片的情况:

一般是默认使用ImageView时,我们会把图片放在drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等文件夹下,或者放入磁盘等存储器中,这种情况下遵循如下规则:

1.图片格式对内存占用没有影响,png、jpg内存占用是一样的,只是在解析的时候占用的内存不一样。

2.ImageView的大小对图片的内存占用没有影响,宽/高为100dp和宽/高为200dp的内存占用是一样的。

3.同一设备的同一张图片放在不同dpi目录下是有影响的,系统会对放在不同目录下的图片做一次分辨率转换,就好像有了一张新的图片,规则如下:

转换后宽度 = 转换前宽度*(设备dpi/目录dpi)

转换后高度 = 转换前高度*(设备dpi/目录dpi)

可以看到,规则一致。

密度

ldpi

mdpi

hdpi

xhdpi

xxhdpi

xxxhdpi

dpi

120

160

240

320

480

640

我们知道内存占用公式为:分辨率*像素点

像素点数据格式一般为ARGB_8888,为4B;其他还有ARGB_4444,为2B; RGB_565,为2B; RGBA_F16,为8B;

一张1080*1920的图片如果放在drawable-xhdpi下,我的设备是480dpi,系统做分辨率转换时就是:

1080*(480/320) = 1620; 1920*(480/320) = 2880;

最后就是1620*2880的分辨率了,根据内存占用计算公式:内存占用=1620*2880*4 = 18662400B≈17.8MB(好大)

所以内存占用公式是没有问题的,只是分辨率和像素点这两个参数是需要计算的,不能直接使用图片本身的分辨率。

通过以上知识点,可知:
3.1 同一设备 的同一张图片放在不同dpi目录下 内存占用是不一样的。

3.2 不同设备 的同一张图片放在同一dpi目录下 内存占用是不一样的。

另外,如果想做图片内存优化 ,就可以从分辨率和像素点两个方面下手,不用ARGB_8888、使用inSampleSize降低Bitmap分辨率等等。可以想象,我们常用的图片加载框架(Glide、Picasso、fresco等)应该使用了上面的思路对图片进行处理,那么他们在处理过后,我们上面的规则还适用吗?

二.使用第三方框架加载图片的情况:

很遗憾,上面的规则已经不适用了!因为各种三方框架对图片进行了处理,还结合了ImageView大小,所以上面的规则基本不适用了。说“基本”是因为第一条,作者没给出定论,其他2条肯定不适用了。不同框架规则不一样:

fresco:

1.不管图片来自于drwable的哪个dpi文件夹,内存占用都是一样的,因为没有经过decodeResource(),且都是适用原图分辨率计算的。

Glide:

1.如果只获取Bitmap对象,那么图片内存占据是按照原图分辨率计算的。如果通过into(imageView)这种,那么就会根据控件大小(dp转化为px)进行转换,然后作为最后分辨率计算;比如我们是1920*984的图片,imageView的宽高为500dp=750px,所以最后就是750*314*4B = 94200B,转换规则并不清楚。

可以看出来,这两个框架已经不管图片来源是在哪个res下、设备dpi是多少了,更不需要根据dpi进行转换,很干脆。

本文是对开头文章做的一点小总结,文章中作者自然做了验证,不同设备dpi和不同res等,还有不同框架。