返回
杰哥的 APK 瘦身实战之旅
Android
2023-12-04 09:21:59
各位观众老爷们,我是杰哥。作为一个吃遍大厂、独步江湖的移动江湖浪人,行走江湖多年,也见识了不少,这不,这次又来和大家聊聊一个江湖中的武林秘籍——APK 瘦身。
**前言**
随着移动互联网的飞速发措,APP 开发也如火如荼,然而,随着APP 功能的不断增强,体积也是越来越庞大。一个庞大臃肿的APK给我们的生活带来诸多不便:
- 安装费时:现在网速再怎么快,也架不住动辄几百兆的 APK 安装包啊!
- 流量浪费:如果你在 4G 网络下,在一个小时内下了 1G 的 APK,那恭喜你,这个月话费稳稳的超支了!
- 用户体验差:作为一个 5G 时代的新新青年,谁还愿意忍受动不动就要等个几分钟的漫长等待呢?
一个轻量级的 APK 无论对开发者还是对终端使用者都有着非常重浚意义。好了,话不多说,闲话少叙,这秘籍在江湖中名唤“APK 瘦身**心** 经》,就让咱一步一步来看看这秘籍中是如何记载这“APK 瘦身**秘** 方”的吧。
**一、APK 瘦身之资源瘦身**
**1、无用资源清理**
* **清理无用 layout 布局** :使用 Android studio 的 Analyze 功能,筛选出无引用的 layout 布局,将其坚决**物理** delete。
* **清理无用 drawable 图片** :同样使用 Analyze 功能,找出从未引用的无用 drawable 图片,**物理** delete。
* **清理无用 anim 动画** :同上,找出无用 anim 资源,**物理** delete。
* **清理无用 style 布局** :同上,清理无用 style 资源,**物理** delete。
**2、资源大小优化**
* **使用更高效的 图片格式** :充分运用 WebP 图片格式,相较于 PNG 图片,体积能缩小一半以上。
* **使用** **Vector Drawable** :Vector Drawable 的可绘制尺寸不受限制,并且体积小,可以**替换** 掉部分大尺寸的 Bitmap Drawable。
* **使用** **AdaptiveVector Drawable** :当需要兼容低版本的 Android SDK(不带 SVG 渲染引擎)时,可选择使用AdaptiveVector Drawable 来替代 Vector Drawable。
* **去除** **9-patch** :9-patch 图片会导致 dex 体积变大,能**不用则不用** 。
* **使用** **View Binding** :View Binding 可以将 layout 中定义的 View 组件转化为常量,进而**避免** 了大量繁琐的 `findById()` 操作,减少了内存的开销。
**二、APK 瘦身之 Gradle 优化**
**1、启用** **minify** **with Dex** **Shrinker**
在 **app/build.gralde** 中启用 Dex 混淆:
```groovy
buildTypes {
release {
// 使用 Dex 混淆进行瘦身
minifyWithDex = true
}
}
2、使用 资源缩小
在 app/build.gralde 中启用资源缩小:
aaptOptions {
// 启用资源缩小
cruncherEnabled = true
}
3、使用 zipAlign
在 app/build.gralde 中启用 zipAlign
进行对齐优化:
buildTypes {
release {
// 启用 ZipAlign
zipAlign {
// 设置 ZipAlign 优化级别
// isFaster 默认为 True
isFaster = false
// 设置 ZipAlign 顺序
// isDeterministic 默认为 True
isDeterministic = true
}
}
}
三、APK 瘦身之 dex 优化
1、方法计数混淆
在 app/build.gralde 中启用方法计数混淆:
buildTypes {
release {
// 启用方法计数混淆
// minifyEnabled 默认为 True
minifyEnabled = true
// 启用混淆调试信息
// 是否输出混淆后的文件
// 默认值为 false
debugInformationFile = 'output.txt'
// 启用混淆报告
// 是否输出混淆报告
// 默认值为 false
useProguard = true
// 设置混淆规则
useLegacyPackaging = true
// 自动混淆,自动将不想混淆的类和成员抽出混淆规则
// 默认值为 false
// 如果该项设为 true,则 unsetMinify 默认为 True,必须要显式 set 为 False 才能禁用自动混淆
optimizeResourcesForDexSize = true
}
}
2、混淆规则优化
- 舍弃无用的方法 :可以舍弃掉调试、日志、无用第三方库中用到的方法,将它们列入混淆规则中。
- 混淆重载方法 :为重载方法指定混淆后的共同名字,可以减小冗余的
方法符
的长度。 - 混淆私有方法 :混淆不含
public
访问权限的私有方法。
四、APK 瘦身之 SO 瘦身
1、裁剪 SO 库
在 app/build.gralde 中裁剪 SO 库:
android {
// 裁剪 SO 库
packagingOptions {
excludeAssets */lib/armeab*
excludeAssets */lib/arm64-v8a*
excludeAssets */lib/mips*
excludeAssets */lib/x86*
}
}
2、拆分 SO 库
- 根据分辨率进行拆分:可以按照不同的屏幕分辨率进行 SO 库的拆分,只将与屏幕分辨率相对应的 SO 库进行打包。
- 根据 ABI 进行拆分:可以按照不同的 ABI 进行 SO 库的拆分,只将与终端机型 ABI 相对应的 SO 库进行打包。
五、APK 瘦身之性能优化
1、减少内存泄漏
- 使用内存泄漏检测工具:使用 LeakCanary 、MAT 等工具,在开发阶段就找出内存泄漏问题。
- 正确使用软引用和强引用:软引用 和强引用 决定了缓存策略。
- 避免使用大内存占用控件:比如 WebView 、Fragment 、View 等控件。
- 关闭不用的服务和广播:Service 、BroadcastReceiver 等组件在不使用时应立即关闭,以防止内存泄漏。
2、减少耗电量
- 优化 UI 线程:避免在 UI 线程中进行耗时运算,使用
Handler
、Thread
等异步调度进行优化。 - 优化动画:避免过度使用动画,使用
Property Animation
、Value Animator
进行优化。 - 关闭不用的后台线程:如果后台线程不再需要,应立即将其关闭,以防止内存泄漏和耗电。
- 使用 JobScheduler 合理调度后台耗时性作业
六、APK 瘦身之实战经验
以上理论在 公司 App 中如何落地呢?举个栗子 :App 体积从 18MB -> 12MB,提速 33%:
瘦身前:
资源瘦身 :
- 移除无用 layout 布局:21 个
- 移除无用 style 布局:40 个
- 移除无用 anim 动画:3 个
- 移除无用 drawabale 图片:120 张
- 使用 Vector Drawable 替代 PNG :20 张
- 使用 WebP 替代 PNG :50 张
- 去除 9-patch :10 处
Gradle 优化 :
- MinifyWithDex 启用
- 资源缩小 启用
- zipAlign 启用
Dex 优化 :
- 方法计数混淆
- 自定义混淆规则
SO 瘦身 :
- 裁剪 SO 库 :不兼容的库裁剪掉
性能优化 :
- 修复内存泄漏:20 处
- 优化耗电量:优化 UI 线程、线程优化
瘦身后的:
APK 体积:12MB ,瘦身 6MB ,**体积缩减 33%