一、优先理解Bitmap内存中占用大小问题
1、图片内存占用基本算法。
Bitmap常用有ARGB_8888、ARGB_565模式。分别代表不同的图片质量。其对应的内存占用大小也不同
ARGB_8888:
RGB_565:透明:8红:8绿:8蓝:8即每一个颜色通道占用8位共32位(即4个字节,8位/字节),占用大小= WIDTH*HEIGHT*4
红:5绿:6蓝:5
2、图片位置对内存大小的影响总共16位(即2个字节),占用大小=WIDTH*HEIGHT*2在程序中可通过如下验证:Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pw_icon); tvImgSize.setText(String.format("宽:%s\n高:%s\n大小:%s", bitmap.getWidth(), bitmap.getHeight(), bitmap.getByteCount())); /** * 宽:77 * 高:77 * 大小:77*77*4=23716b=23.1kb */
影响因素2点:
①、(次要)当前设备自身dpi(可更改DPI)②、(主要)图片资源存放位置由于实际上decodeResource原码时间过程中调用decodeResourceStream方法,在未设置option时,会自动创建option,并通过inDensity和inTargetDensity计算缩放比例,因此下文提到的宽高并非完全对应图片资源的真实宽高像素数,但由于对应实现规则是不变的,因此不纳入影响因素当中。 inDensity为当前资源所在目录影响,inTargetDensity为目标设备的实际密度DPI影响,实际密度DPI可通过下面两种方式得到。adb shell wm density→ getResources().getDisplayMetrics().densityDpi;//手机当前设置的dip而非是真实物理dip(可修改)
以小米MIX为例,
设备物理dpi(取决于硬件屏幕,不可更改)为365左右,对应XXhdpi资源,当图片资源位于XXhdpi目录下时,得到bitmap,大小约为宽 ×高 ×4当图片资源位于hdpi目录下时,得到bitmap,大小约为(宽 ×2) ×(高 ×2)×4当图片资源位于XXXhdpi目录下时,得到的bitmap,大小约为(宽 ×0.75)×(高 ×0.75)×4
总结:系统会根据设备DPI(屏幕实际DPI)优先选择对应的资源目录选取图片,当图片位于高于当前对应等级时,或主动通过命令缩小当前设备的设置DPI,系统会认为图片是为更高dpi设备准备,所以会将图片缩小(内存占用变小)。当图片位于低于当前等级路径下时,或主动通过命令增大当前设备的设置DPI,系统则会对图片进行放大(内存占用变大)。Bitmap在内存中占用大小只与图片被加载时的尺寸质量等有关,与图片本身的大小无关,格式无关.
注:
系统对图片查找顺序,对应等级→更高级→nodpi→低级递增,如:xxhdpi→xxxhdpi →nodpi→mdpi→hdpi→xxhdpi缩放倍数关系为,dpi范围最大值的倍数关系
dpi范围 密度 0dpi~120dpi ldpi 120dpi~160dpi mdpi 160dpi~240dpi hdpi 240dpi~320dpi xhdpi 320dpi~480dpi xxhdpi 480dpi~640dpi xxxhdpi
扩展:
最佳图片资源尺寸选择
Android 开发过程中。一般来说、图片资源存放于Drawable目录下,对于不同Density的设备,区分mdip、hdpi、xhdpi、xxhdpi、xxxhdpi的区分,google官方建议提供多套图片资源用于对应的设备上。但实际开发过程中,为节省apk大小以及UI设计成本,一般仅提供一套图片资源,该种情况下,就目前市场设备dpi而言,一般采用xxhdpi资源比较合适,由于系统对于设备的选择为从当前等级逐级向上,再到最低等级逐级向上,高等级的会被缩小,低等级的会被放大。而像素小的图片放大将影响图片质量,而大图片缩小则不会有明显影响,所以尽量采取大尺寸图片,同时,由于市面主流设备介于320dpi~480dpi之间,而480dpi~640dpi设备较少,如果采用XXXhdpi为标准则将会增大更多的APK大小,故一般最佳设计尺寸为xxhdpi即1080p