Android 内存优化-车载图片资源

1,330 阅读4分钟

查看设备 DPI

在Android中,屏幕密度通常以DPI(dots per inch,每英寸点数)来表示。DisplayMetrics类中有几个与屏幕密度相关的字段:

  • density:屏幕密度,即屏幕每英寸的像素点数。
  • densityDpi:屏幕密度的DPI值,通常与density字段相同。
  • scaledDensity:缩放后的屏幕密度,用于应用的UI缩放。
  • xdpiydpi:屏幕的物理密度,即屏幕每英寸的水平和垂直像素点数。

densitydensityDpi通常用于获取屏幕的密度值,它们提供了一个浮点数,表示屏幕密度相对于 160dpi(中等密度屏幕)的比例。例如,如果屏幕密度是 320dpi,那么densitydensityDpi的值将是 2.0。

Bitmap的内存大小=图片长度∗图片宽度∗单位像素点占用的字节数

private fun display(){
    // 获取 DisplayMetrics 实例
    val displayMetrics = DisplayMetrics()
    windowManager.defaultDisplay.getMetrics(displayMetrics)

    // 获取屏幕宽度和高度(像素)
    val widthPixels = displayMetrics.widthPixels
    val heightPixels = displayMetrics.heightPixels

    // 获取屏幕宽度和高度(dp)
    val widthDp = widthPixels / displayMetrics.density
    val heightDp = heightPixels / displayMetrics.density

    // 获取屏幕密度
    val density = displayMetrics.density
    val densityDpi = displayMetrics.densityDpi

    // 打印屏幕尺寸和分辨率
    LogUtils.i(TAG,"屏幕宽度 (像素): $widthPixels")
    LogUtils.i(TAG,"屏幕高度 (像素): $heightPixels")
    LogUtils.i(TAG,"屏幕宽度 (dp): $widthDp")
    LogUtils.i(TAG,"屏幕高度 (dp): $heightDp")
    LogUtils.i(TAG,"density  : $density")
    LogUtils.i(TAG,"densityDpi  : $densityDpi")
}

设备分辨率

  • 屏幕宽度 (像素): 1920
  • 屏幕高度 (像素): 931
  • 屏幕宽度 (dp): 1442.2534
  • 屏幕高度 (dp): 699.3427
  • density : 1.3312501
  • densityDpi : 213

常见密度标识符和对应的密度值:

  • drawable:默认,未指定密度,相当于mdpi(density= 1.0 , densityDpi = 160)
  • drawable-mdpi:中密度,密度值为 1.0
  • drawable-hdpi:高密度,密度值为 1.5
  • drawable-xhdpi:超高密度,密度值为 2.0
  • drawable-xxhdpi:超超高密度,密度值为 3.0
  • drawable-xxxhdpi:超超超高密度,密度值为 4.0

单位像素占用的字节数由颜色模式Bitmap.Config决定,即ARGB 颜色通道,主要有6种类型:

  • ALPHA_8:只有一个alpha通道,8bit,每个像素占1Byte;
  • ARGB_4444:包含红绿蓝alpha4个通道,每个通道4bit,每个像素占2Byte;
  • ARGB_8888:包含红绿蓝alpha4个通道,每个通道8bit,每个像素占4Byte;
  • RGB_565:包含红绿蓝3个通道,其中红色占5bit,绿色占6bit,蓝色占5bit,每个像素占2Byte;
  • RGBA_F16:包含红绿蓝alpha4个通道,每个通道8bit,每个像素占4Byte;
  • HARDWARE:ARGB_8888的特殊配置,Bitmap会直接存储在显存中。

主要使用 ARGB_888 8和 RGB_565 两种配置,ARGB_8888支持透明通道,且颜色质量更高,RGB_565不支持透明通道,但整体内存占用少了一半

内存占用计算

  1. drawable目录下
  • 假设图片的实际尺寸为 1920x1080 像素。
  • 每个像素的内存占用通常为4字节(使用Bitmap.Config.ARGB_8888)。
内存占用计算公式为:
    内存占用 (bytes)=宽度 (pixels)×高度 (pixels)×4
计算:
    内存占用=1920×1080×4=7,136,640 bytes≈7.9 MB

项目中图片改用 1920*931 像素后的内存大小:内存占用=1920×931×4=7,136,640 bytes≈6.8 MB,每张壁纸图片节省约 7.9 MB - 6.8 MB = 1.1 M 的内存空间

  1. drawable-hdpi目录下
  • hdpi对应的密度为 240dpi,通常在hdpi目录下,图片会被缩放为设备密度的比例。

  • 由于设备的实际 dpi 为 213(根据 density 计算),因此需要进行缩放。

  • 计算缩放比例:

      缩放比例=213/240≈0.8875
    
  • 计算缩放后的图片尺寸:

    新宽度=1920×0.8875≈1700 pixels
    新高度=1080×0.8875≈958 pixels
    
  • 内存占用计算:

     内存占用=1700×958×46,514,400 bytes6.2 MB
      
    

项目图片改用 1920*931 像素后的内存大小:

  • 新高度=931×0.8875≈826 pixels ,
  • 内存占用=1700×826×4≈5,634,800 bytes≈5.4 MB,
  • 每张壁纸图片节省约 6.2 MB - 5.4 MB = 0.8 MB 的内存空间。

理论提升值:当图片放在 hdpi 且用适当的分辨率:

  • 在 drawable 目录下,图片的内存占用约为 7.9 MB。
  • 在 drawable-hdpi 目录下,图片的内存占用约为 6.2 MB。
  • 在 drawable-hdpi 目录下,图片改用 1920*931 分辨率,每张节省内存空间:7.9 MB - 5.4 MB = 2.5 MB,内存优化率达到 32%