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

相关推荐
爷傲奈我何!5 分钟前
小程序中实现音频播放(原生 + uniapp)
前端·vue.js
Json_10 分钟前
uni-app 框架 调用蓝牙,获取 iBeacon 定位信标的数据,实现室内定位场景
前端·uni-app·蓝牙
日升11 分钟前
手把手带你掌握Zustand:轻量级React状态管理利器
前端·react.js·状态机
Copy_Paste_Coder11 分钟前
35岁大龄码农,用cursor独立做副业经历分享
前端·程序员
jqq66613 分钟前
(二)「造轮子」我也写了个Vue3脚手架!(项目环境搭建)
前端·javascript·vue.js
Json_14 分钟前
vue2 + element-ui 开发网站拼图小游戏-前端项目
前端·vue.js·element
顾名思远义16 分钟前
VxeGRid树形表格编辑难点
前端·vue.js
逆袭的小黄鸭18 分钟前
单线程下的高效协作:JavaScript 事件循环机制详解
前端·javascript
0基础学习者19 分钟前
按键消抖(用状态机实现)
前端·笔记·fpga开发·verilog·fpga
zooKevin22 分钟前
前端实现docx格式word文件预览,可以兼容原生、vue2、以及uni-app 项目,详细步骤。
前端·uni-app·word·docx