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

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

1 移除无用资源

使用 lint 静态代码分析工具 查找出未使用的 res 资源。

注意 assertlib 下的未使用资源无法检测出来,其中 assert/ 资源引用采用的是反射方法。 除了检测工具外,Gradle 还支持在打包编译的时候自动移除无用资源,使用 shrinkResources

groovy 复制代码
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 图片加载库 GlidePicassoFresco 的选择,将依赖库的体积大小作为选用的衡量标准之一。

另外,如果只是使用某个工具库的其中一个(小)功能,是否可以考虑将其下载下来自行修改,适当移除不需要的功能代码,从而减少依赖库的体积。

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 复制代码
<?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),如果不需要,可以手动关闭:

groovy 复制代码
buildTypes.all { isCrunchPngs = false }

需要注意的是,isCrunchPngs 在 release 默认打开(这会增加编译时间),debug 下默认关闭。

选用第三方工具进行不同格式图片压缩:

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)绘制,不适合大面积的图像绘制,有一定的性能消耗。

例子:

ini 复制代码
<!-- 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>

渲染生成:

还有动画效果也可以使用 vector graphics 来实现,参考 AnimatedVectorDrawableCompat

(对比使用逐帧动画,需要放入大量的单帧图片组合一个动画,极大增加了apk包大小!)

参考

Reduce your app size

相关推荐
摸鱼的春哥17 分钟前
春哥的Agent通关秘籍07:5分钟实现文件归类助手【实战】
前端·javascript·后端
念念不忘 必有回响20 分钟前
viepress:vue组件展示和源码功能
前端·javascript·vue.js
C澒26 分钟前
多场景多角色前端架构方案:基于页面协议化与模块标准化的通用能力沉淀
前端·架构·系统架构·前端框架
崔庆才丨静觅27 分钟前
稳定好用的 ADSL 拨号代理,就这家了!
前端
江湖有缘29 分钟前
Docker部署music-tag-web音乐标签编辑器
前端·docker·编辑器
恋猫de小郭2 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端