7
7
1 . 前言
8
8
2 . 包组成
9
9
3 . 代码优化
10
- 4 . Native Library 优化
11
- 5 . 资源优化
10
+ 1 . ProGuard & R8
11
+ 2 . 去除冗余赋值
12
+ 3 . 删除无副作用的代码
13
+ 4 . 减少定义的方法或字段数
14
+ 5 . 去掉 Debug 信息或行号
15
+ 6 . Dex 分包、Dex 压缩
16
+
17
+ 4 . 资源优化
18
+ 1 . 资源路径混淆
19
+ 2 . 无用资源移除
20
+ 3 . 去除重复资源
21
+ 4 . 资源动态下发
22
+ 5 . 图片压缩、转化
23
+ 6 . 减少资源配置
24
+
25
+ 5 . Native Library 优化
26
+ 1 . 开启 LTO
27
+ 2 . Library 压缩
28
+ 3 . Library 合并和裁剪
29
+
12
30
6 . 参考
13
31
14
32
#### 前言
15
33
16
- 包体积优化主要影响的下载转化率,除此之外包体积对应用性能也是有影响的,表现在安装时间、运行内存、ROM 空间。应用在首次安装启动时,会编译 odex 文件,对于低端机来说,过多的 dex 文件编译会严重影响冷启动时间(解决方案 [ BoostMultiDex] ( https://github.com/bytedance/BoostMultiDex ) )。应用在运行时,Resource 资源、Library 以及 Dex 类加载这些都会占用不少的内存。安装包在解压后,占用 ROM 空间可能会翻倍,对 ROM 空间占用也会有一定压力。
34
+ 包体积大小主要影响的下载转化率,以 Google 的[ 数据统计] ( https://medium.com/googleplaydev/shrinking-apks-growing-installs-5d3fcba23ce2 ) 每减少 10M 大小,有 1.5% 的下载转化率提升。
35
+
36
+ 除此之外包体积对应用性能也是有影响的,表现在安装时间、运行内存、ROM 空间。应用在首次安装启动时,会编译 odex 文件,对于低端机来说,过多的 dex 文件编译会严重影响冷启动时间(解决方案 [ BoostMultiDex] ( https://github.com/bytedance/BoostMultiDex ) )。应用在运行时,Resource 资源、Library 以及 Dex 类加载这些都会占用不少的内存。安装包在解压后,占用 ROM 空间可能会翻倍,对 ROM 空间占用也会有一定压力。
17
37
18
38
#### 包组成
19
39
@@ -148,9 +168,53 @@ Dex 信息有效率 = defind methods 数量 / reference methods 数量
148
168
149
169
当 Dex 非常多的时候会增加应用的安装时间,对于十个以上的 Dex,首次生成 ODEX 的时间可能就会达到分钟级别。
150
170
171
+ #### 资源优化
172
+
173
+ 在我们的安装包中,资源相关的文件具体有下面几个,它们都是我们需要优化的目标文件。
174
+
175
+ | 文件/目录 | 描述 |
176
+ | -------------- | ---------------------------------------------------------- |
177
+ | res/ | 存储编译后的资源文件,例如 Drawble、Layout 等 |
178
+ | assets/ | 应用程序的资源,应用程序可以使用 AssetManager 来检索该资源 |
179
+ | resources.arsc | 编译后的二进制资源文件 |
180
+
181
+ ##### 资源路径混淆
182
+
183
+ 目前 R8 已经支持资源路径混淆,并且也支持白名单配置。AndResGuard 可能要退出历史舞台了。
184
+
185
+ ##### 无用资源移除
186
+
187
+ 可以通过 Lint 来移除未使用的资源,不过实际上并不会直接删除该资源,而是用虚拟文件替换了,虚拟文件文件的大小也不小,为啥不能替换成空文件呢?
188
+
189
+ 其次就是无法移除 assets 目录下的资源文件。
190
+
191
+ ##### 去除重复资源
192
+
193
+ 可以通过生成资源的 md5 来解决。
194
+
195
+ ##### 资源动态下发
196
+
197
+ 对于某些资源文件,可以采取动态下发的形式,比如比较大的 lottie 资源等等。
198
+
199
+ ##### 图片压缩、转化
200
+
201
+ 我们可以压缩 png 图片,或者对于 minSDK > 19 的,可以使用 webp 格式的图片。
202
+
203
+ ##### 减少资源配置
204
+
205
+ 比如配置 resConfig 只保留中文简体和 xxhdpi 的资源等、部分 shape animation drawable 可以使用代码的方式去写。
206
+
151
207
#### Native Library 优化
152
208
153
- 对于 Native Library,传统的优化方法可能就是去除 Debug 信息、使用 c++_ shared 这些。那么我们还有没有更好的优化方法呢?
209
+ Android Gradle Plugin 在编译 so 库时,首先产生的是带有调试信息和符号表的 so(任务名为 externalNativeBuildRelease),之后会对刚产生的带调试信息和符号表的 so 进行 strip 优化(移除调试信息和符号表),就得到了最终打包到 apk 或 aar 中的 so(任务名为 stripReleaseDebugSymbols)。
210
+
211
+ 之所以先编译出带有调试信息和符号表的 so,原因在于需要使用带调试信息和符号表的 so 对崩溃调用栈进行还原。
212
+
213
+ 除了 AGP 自带的优化操作?还有哪些手段可以做呢?
214
+
215
+ ##### 开启 LTO
216
+
217
+ LTO 是 Link Time Optimization 的缩写,即链接期优化。LTO 能够在链接目标文件时检测出 DeadCode 并删除它们,从而减少编译产物的体积。比如某个 if 条件永远为假,那么 if 为真下的代码块就可以移除。也就类似于 R8 的条件编译。
154
218
155
219
##### Library 压缩
156
220
@@ -164,20 +228,6 @@ Dex 信息有效率 = defind methods 数量 / reference methods 数量
164
228
165
229
在 Android 4.3 之前,进程加载的 Library 数量是有限制的,在编译过程,我们可以自动将部分 Library 合并成一个。
166
230
167
- #### 资源优化
168
-
169
- 在我们的安装包中,资源相关的文件具体有下面几个,它们都是我们需要优化的目标文件。
170
-
171
- | 文件/目录 | 描述 |
172
- | ------------------- | ------------------------------------------------------------ |
173
- | res/ | 存储编译后的资源文件,例如 Drawble、Layout 等 |
174
- | assets/ | 应用程序的资源,应用程序可以使用 AssetManager 来检索该资源 |
175
- | META-INF/ | 该文件夹一般存放于已经签名的 APK 中,它包含了 APK 中所有文件的签名摘要等信息 |
176
- | resources.arsc | 编译后的二进制资源文件 |
177
- | AndroidManifest.xml | Android 的清单文件,用于描述应用程序的名称、版本、所需权限、注册的四大组件 |
178
-
179
-
180
-
181
231
#### 包压缩
182
232
183
233
安装完 Redex 之后:
@@ -244,5 +294,7 @@ ANDROID_SDK=/Users/omooo/Library/Android/sdk redex app-debug.apk -o app-resize.a
244
294
245
295
[ 百度 App Android 包体积优化实践(一)总览] ( https://mp.weixin.qq.com/s/PrHvFczQzOzbbnnbMb4PVg )
246
296
297
+ [ 百度 App Android 包体积优化实践(二)Dex 行号优化] ( https://mp.weixin.qq.com/s/zEAwm0om8MPle6hgaizFGw )
298
+
247
299
[ 得物 App 包体积治理之路] ( https://mp.weixin.qq.com/s/1aAgY4OPnZl650Q8vD3LNA )
248
300
0 commit comments