我们之前分析过瘦身优化:App瘦身优化
这篇文章我们继续分析瘦身优化
“每个字节都应该为用户体验服务,冗余即是对用户的不敬”
一、整体思路 & 优化流程
- 目标明确
- 明确一个目标:例如 安装包 ≤ 50MB 或 *相比当前减少 30%*。
- 区分:安装包体积(APK/AAB**)** vs 安装后占用空间,手段有所不同。
- 量化分析
- 使用工具:
Analyze APK(Android Studio 内置):看各目录和 .dex 的体积占比。apktool/bundletool解包进一步分析。
- 先找“大头”:一般是
lib/(so库)res/(图片、音视频、字体)classes*.dex(代码)- assets(离线包、H5、模型文件等)
- 使用工具:
- 优先级
- P0:资源 & 多余依赖(通常最容易减 20~40%)
- P1:代码混淆压缩 & 多dex瘦身
- P2:架构升级(Android App Bundle**、动态特性模块拆分)**
- P3:深度方案(重构架构、替换大模块)
二、基础配置层面(低成本高收益)
如果还在发 APK,建议改为 AAB + Google Play/各应用市场的分发优化:
- 好处:
- 自动做 ABI 分包(只下当前CPU架构的 so)
- 自动做 语言资源拆分(只下当前语言)
- 自动做 密度拆分(按屏幕分发资源)
- 配置(示意):
android {
bundle {
language {
enableSplit = true
}
density {
enableSplit = true
}
abi {
enableSplit = true
}
}
}
- 确保开启:
buildTypes {
release {
minifyEnabled true // 开启代码压缩+混淆
shrinkResources true // 删除未使用的资源
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
- 注意:
- 线上一定要配好
keep规则,避免反射导致崩溃。 - 可以开启
-whyareyoukeeping辅助分析为啥某些类没被清掉。
- 线上一定要配好
三、资源瘦身(通常收益最大)
-
图片资源优化
-
格式选择
- 优先使用 矢量图(Vector Drawable) 替代多分辨率 PNG 图标(尤其是图标、简单图形)。
- 位图资源优先考虑:
- WebP(有损/无损)
- 适当场景考虑 AVIF(Android 12+,视用户覆盖情况)
-
压缩图片
- 使用专业工具离线批量压缩:
- TinyPNG、ImageOptim 等(出包前 pipeline 中跑一遍)。
- 控制图片分辨率:UI 不需要 4K 大图的话就不要用。
- 使用专业工具离线批量压缩:
-
去掉冗余分辨率
- 只保留必要的
xxxhdpi/xxhdpi等,避免同一资源多个密度重复。 - 使用 App Bundle 的 density split 后,可以适度减少本地冗余。
- 只保留必要的
-
音视频资源
- 优先采用 在线加载+缓存,避免大体积音视频直接打进包。
- 必须内置的音频:
- 采用较高压缩率格式(如
ogg、aac)。 - 控制长度,避免整首歌打入包。
- 采用较高压缩率格式(如
- 必须内置的视频:
- 降低分辨率、码率,或做短片/循环片段。
- 考虑 H.265/VP9(取决于最低兼容版本)。
- 如果使用自定义字体:
- 尽量只内嵌 1~2 种主要字体。
- 使用 子集化字体(只保留需要的字符范围,例如
latin、basic CJK),减少TTF/OTF大小。 - 多语言字体尽量分拆,通过在线下载或按需包加载。
- 若使用 AAB,可以开启语言拆分,安装时只下当前语言。
- 评估是否真的需要支持所有语言:
- 去掉几乎没有用户的语言资源。
- 或采用在线配置方式加载部分文案,避免全部内置。
- 开启
shrinkResources后,配合工具排查:- Android Studio →
Analyze → Inspect Code查找 unused resources。 - 注意:被反射 / 动态拼接引用的资源,要通过
tools:keep或 proguard keep 保护。
- Android Studio →
- 清理:
- 不再使用的旧图标、老主题资源、废弃布局文件。
- 旧的引导页图片、运营活动资源等。
四、代码维度瘦身(dex / 依赖)
-
依赖梳理与瘦身
-
检查 Gradle 依赖树
-
./gradlew app:dependencies- 找出:
- 重复的库(如同一个功能有多个不同依赖)
- 只用到一个小功能却引入非常大的库(如整套 analytics / IM / video SDK)
- 找出:
-
替换/删除大依赖
- 大而全的 SDK → 精简版 SDK 或自研轻量实现。
- 多个 JSON 库 → 统一为一个(如 Gson / Moshi),去掉其他。
- 多个网络库 → 统一到 OkHttp/Retrofit 一套。
-
使用 **
implementation 而非 api**- 避免传递性依赖膨胀其他 module。
-
代码结构优化
- 尽量降低方法数量(方法数过多会产生 multi-dex,dex 体积上升):
- 清理未使用的老代码(弃用模块、旧业务逻辑)。
- 将一些复杂工具类拆分为模块依赖,按需加载或仅在特定版本使用。
- 对 插件化/热修复框架 做取舍:
- 部分框架自身体积不小,要评估是否仍有必要。
在 Android Studio 中检查项目模块(Module)之间的依赖关系,主要有 可视化界面查看、Gradle 命令分析、第三方插件辅助 三种方式,覆盖从快速预览到详细分析的场景,以下是具体操作步骤:
1)、可视化界面:快速查看模块依赖(最常用)
Android Studio 内置了依赖关系可视化工具,支持直观查看模块间的直接 / 间接依赖,操作简单:
适合快速核对单个模块的依赖(包括本地模块 + 远程库):
- 打开 Android Studio,进入项目;
- 两种打开方式:
- 顶部菜单栏 →
File → Project Structure(快捷键:Ctrl+Alt+Shift+S/ MacCmd+Alt+Shift+S); - 右侧「Gradle」面板 → 选中项目根目录 → 右键 →
Open Module Settings;
- 顶部菜单栏 →
- 在左侧面板选择「Modules」,然后选中你要检查的模块(如
app); - 切换到右侧「Dependencies」标签页:
- 列表中「Module dependency」类型即为 本地模块依赖(如
:moduleA、:library); - 其他类型(如
Library dependency)为远程库依赖,可忽略;
- 列表中「Module dependency」类型即为 本地模块依赖(如
- 若要查看其他模块的依赖,切换左侧模块列表即可。
适合查看 整个项目的所有模块依赖关系(包括模块间的间接依赖),图形化展示更清晰:
- 顶部菜单栏 →
View → Tool Windows → Gradle(打开 Gradle 面板); - 在 Gradle 面板中,展开你的项目 → 选中要分析的模块(如
app)→ 展开Tasks → help; - 右键点击
dependencies任务 → 选择Run '模块名:dependencies'(如Run 'app:dependencies'); - 执行完成后,底部「Run」面板会输出文本格式的依赖树;
- 若要可视化图形:
- 顶部菜单栏 →
Analyze → Analyze Dependencies...; - 在弹出的窗口中,选择要分析的模块(可多选,如
app、moduleA),点击「OK」; - 生成依赖关系图,支持:
- 拖动节点调整布局;
- 右键节点 →
Show Dependencies查看该模块的详细依赖; - 筛选「Only Modules」只显示本地模块依赖(隐藏远程库)。
- 顶部菜单栏 →
2)、Gradle 命令:详细分析依赖(支持过滤和导出)
如果需要更精确的依赖分析(如查找重复依赖、间接依赖来源),可通过 Gradle 命令行执行,Android Studio 内置终端直接支持:
- 底部面板 → 切换到「Terminal」标签(若未显示,通过
View → Tool Windows → Terminal打开)。
在终端中输入以下命令,按回车执行:
| 命令(Windows/Mac/Linux 通用) | 作用 |
|---|---|
| ./gradlew :app:dependencies | 查看 app 模块的所有依赖(本地模块 + 远程库),按配置(debug/release)分类 |
| ./gradlew :moduleA:dependencies | 查看指定模块(如 moduleA)的依赖 |
| ./gradlew dependencies | 查看整个项目所有模块的依赖(输出较多,不推荐) |
默认输出包含大量远程库依赖,可通过 grep(Mac/Linux)或 findstr(Windows)过滤,只保留本地模块依赖(模块名通常以 : 开头,如 :moduleA):
- Mac**/Linux**:
./gradlew :app:dependencies | grep --color ":module" # 筛选包含 ":module" 的依赖(模块名通常含 module)# 或精确匹配本地模块(格式为 :模块名)
./gradlew :app:dependencies | grep -E ":([a-zA-Z0-9_]+)" --color
- Windows(CMD** 终端)**:
gradlew :app:dependencies | findstr ":module"
- Windows(PowerShell** 终端)**:
.\gradlew :app:dependencies | Select-String ":module"
将依赖分析结果导出为文本文件,方便后续查看:
- Mac/Linux:
./gradlew :app:dependencies > app_dependencies.txt
- Windows:
gradlew :app:dependencies > app_dependencies.txt
执行后,项目根目录会生成 app_dependencies.txt 文件,包含完整依赖信息。
3)、第三方插件:增强型依赖分析(复杂项目推荐)
如果项目模块多、依赖关系复杂,可使用第三方插件提供更强大的分析功能:
- 功能:可视化依赖树、检测重复依赖、冲突依赖报警、导出详细报告;
- 安装步骤:
- 顶部菜单栏 →
File → Settings → Plugins(Mac:Android Studio → Settings → Plugins); - 搜索「Dependency-Check」,点击「Install」安装,重启 Android Studio;
- 顶部菜单栏 →
- 使用:
- 右键项目根目录 →
Dependency Check → Analyze Project; - 生成交互式依赖报告,支持筛选模块、查看依赖链路、定位冲突依赖。
- 右键项目根目录 →
Gradle Dependency Helper:快速搜索依赖、查看最新版本、一键替换依赖;Dexcount Gradle Plugin:分析依赖对应的方法数(辅助优化包体积)。
4)、关键说明
- 模块依赖格式:本地模块依赖在
build.gradle中表现为implementation project(':moduleA')(Android Gradle Plugin 3.0+),旧版本可能是compile project(':moduleA'); - 间接依赖:若
app依赖moduleA,moduleA依赖moduleB,则app间接依赖moduleB,通过「Dependency Graph」或 Gradle 命令可查看这种传递依赖; - 依赖冲突:若多个模块依赖同一库的不同版本,Gradle 会默认选择最高版本,可通过
./gradlew :app:dependencies查看冲突解决结果(标注(variant: ...))。
通过以上方法,可全面覆盖从「快速预览」到「详细分析」的模块依赖检查需求,根据项目复杂度选择对应方式即可~
五、Native so 库瘦身
- 常见 ABI:
armeabi-v7a,arm64-v8a,x86,x86_64。 - 实战策略:
- 绝大多数线上版本可以只保留
armeabi-v7a+arm64-v8a。 - x86 系列设备占比非常低,可改为通过渠道单独提供。
- 绝大多数线上版本可以只保留
- Gradle 配置示例:
android {
defaultConfig {
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
}
- 许多 IM、音视频、地图 SDK 默认集成全 ABI 的 so。
- 尽量使用官方提供的 精简包 或“按需模块化包”。
- 如果 SDK 允许手动删去某些 ABI 目录,可在构建前处理。
- 编译选项优化:
- 打开
-Os或-Oz(以减小体积为目标)。 - 去掉不必要的调试符号。
- 打开
- 删除无用的 native 方法、旧接口。
六、模块拆分与动态交付(Dynamic Feature)
如果 App 已经比较大(>100MB),可以考虑:
- 按业务模块拆分
- 核心流程(登录/首页/基础浏览)作为 base module。
- 低频/重度功能做 Dynamic Feature Module(例如:AR 模块、重度编辑器、游戏、视频编辑等)。
- 触发更新或安装
- 用户进入对应页面前再下载对应动态模块。
- 拆分原则
- 按“使用频次”和“体积大小”做划分:
- 高频 + 小体积:放 base。
- 低频 + 大体积:拆动态模块。
- 避免过度拆分导致开发和维护成本极高。
- 按“使用频次”和“体积大小”做划分:
七、启动后按需加载 / 延迟加载
- 减少首包必须内容
- 把不影响“首屏体验”的功能延后加载或在线下发:
- 运营活动资源
- 辅助工具模块(分享、扫一扫、埋点可稍晚初始化)
- 把不影响“首屏体验”的功能延后加载或在线下发:
- 在线资源 + 本地缓存
- 部分资源(尤其大图 / 大配置)改为首启后后台下载到本地。
- 注意控制失败回退策略,防止无网时完全不可用。
八、构建流程中的自动化检查
- 持续集成(CI**)里增加体积阈值检查**
- 每次构建统计:
- 包体积
- 各目录大小(lib/res/assets/dex)
- 超过阈值时报警,避免长期“野蛮生长”。
- 每次构建统计:
- 自动压缩/转换 Pipeline
- 在打包前自动执行:
- 图片压缩脚本
- 字体子集化
- 删除不再使用的资源(配合白名单)
- 在打包前自动执行:
九、具体优化措施
1、assets目录优化
1)、删除字体文件,字体文件由系统预置 (缩减16MB)

把app的这两个字体文件删除,由系统去


885

被折叠的 条评论
为什么被折叠?



