这是 Android 官方文档给出的一些削减包体积的主张,最近正好在看这方面内容,顺手记载、分享一下。本文主要是针对 Android 的资源(Resource) 相关优化主张。

1 移除无用资源

运用 lint 静态代码剖析东西查找出未运用的 res 资源。

注意 assertlib 下的未运用资源无法检测出来,其间 assert/ 资源引用采用的是反射办法。 除了检测东西外,Gradle 还支撑在打包编译的时分主动移除无用资源,运用 shrinkResources

android {
    // Other settings
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

这儿 minifyEnabled 需求一同翻开,即代码紧缩。这样编译的时分会先用 R8 进行无用代码移除,然后 gradle 插件进行无用资源的移除。详细运用参考:Shrink, obfuscate, and optimize your app

除此之外,还能够运用 resConfig 装备针对指定的 flavor 来打包指定的资源。比方外发包的图片和第一方的包的资源不一样,装备在不同的文件夹下,打包的时分就能够只打包指定的文件夹资源,这样也能削减必定的体积。

2 削减依靠库巨细

开发的时分,在挑选第三方东西库时,需求关注一下该库的巨细。比方 Android 图片加载库 Glide、Picasso、Fresco 的挑选,将依靠库的体积巨细作为选用的衡量标准之一。

另外,假如只是运用某个东西库的其间一个(小)功能,是否能够考虑将其下载下来自行修正,适当移除不需求的功能代码,然后削减依靠库的体积。

3 原生动画图片支撑

运用 ImageDecoder 原生 API 支撑带动画的 GIF 和 WebP 的图片文件格局,然后删除第三方库削减包体积。

要求 Android 11 以上才支撑

4 支撑特定分辨率

从 Android 4.4 开端,支撑 ldpi, mdpi, tvdpi, hdpi, xhdpi, xxhdpixxxhdpi 这么多的分辨率(屏幕密度,density),但是没有必要给每个分辨率都制作对应的图片资源。

也许你的用户只有 0.1% 的人需求 ldpi

这个时分,其实我们只需求一种分辨率的文件夹,比方 drawable-nodpi/,关于其他的,体系会主动适配(扩大缩小)

官方引荐至少有一种分辨率 xxhdpi

5 运用 drawable 或代码渲染图片

有些单色布景图片其实不需求静态的图片文件,运用 Drawable 对象(xml 里的 )能够在运转的时分制作出来,然后节省出静态图片文件的巨细。

对应的,运用代码来生成某些简略的作用图(render from code),比方页面布景设置为纯色。

比较运用图片文件,能够减小必定的包体积巨细。

6 复用资源

某些情况下,两张图片可能除了视点或许色彩不一样,其他都是一样的,这个时分,我们就不引荐运用2张图片,能够经过代码来上色或许旋转。

图片的纯上色(改动色彩),大于 Android 5.0(API 21) 的体系能够运用 android:tinttintMode ,小于 Android 5.0 的版本运用 ColorFilter 来完成。

改动图片的旋转视点,比方上箭头改为下箭头这种,运用下面这样即可:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_thumb_up"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromDegrees="180" />

7 紧缩图片资源文件

官方内置的东西 aapt,在编译的时分,会主动对 res/drawable/ (其他目录无效,比方 asset/ )里面的图片进行无损紧缩(lossless compression),假如不需求,能够手动封闭:

buildTypes.all { isCrunchPngs = false }

需求注意的是,isCrunchPngs 在 release 默许翻开(这会添加编译时间),debug 下默许封闭。

选用第三方东西进行不同格局图片紧缩:

  • PNG 运用 Pngcrush (引荐)、pngquant、zopfli
  • JPEG 运用 packJPG、Guetzli

8 运用 WebP 文件格局

Android 3.2(API 13) 之后开端支撑 WebP 图片格局。

WebP 比较 JPEG 和 PNG 有更好的紧缩功率(即紧缩的体积更多,损失越小),能够直接在 Android Studio 里面将 BMP, JPG, PNG 或许静态 GIF 图片转换为 WebP 格局。

JPEG 为有损紧缩(lossy compression) PNG 为无损数据紧缩,主要体现在通明度上的改变。(lossless data compression,a raster-graphics file format)

9 运用矢量图形(vector graphics)

矢量图形是一种与分辨率无关的图片,100字节巨细的文件能够描绘出充满整个屏幕的高清图片。

矢量图形在代码里用 VectorDrawable 表示。

但是有必定的功能问题。矢量图形本质上就是一系列 xml 数据,Android 体系依据矢量图形的“描绘”调用 cpu\gpu 去制作出来一张图:比方x坐标以上涂满红色,y坐标以下涂满绿色,哪里哪里填上灰色…

合适用于小面积的图标(icon)制作,不合适大面积的图画制作,有必定的功能消耗。

比如:

<!-- res/drawable/battery_charging.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="24dp"
    android:width="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
   <group
         android:name="rotationGroup"
         android:pivotX="10.0"
         android:pivotY="10.0"
         android:rotation="15.0" >
      <path
        android:name="vect"
        android:fillColor="#FF000000"
        android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
        android:fillAlpha=".3"/>
      <path
        android:name="draw"
        android:fillColor="#FF000000"
        android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/>
   </group>
</vector>

渲染生成:

Android 包体积优化建议-资源篇

还有动画作用也能够运用 vector graphics 来完成,参考 AnimatedVectorDrawableCompat

(比照运用逐帧动画,需求放入很多的单帧图片组合一个动画,极大添加了apk包巨细!)

参考

Reduce your app size