前言:
你是否曾今被迫接手一个浩瀚又陌生的项目,面对繁杂的代码总有些力不从心且心声厌倦;你是否曾今经历码字五分钟,编译两小时;你是否曾今在下载某一款app时因为要下载很久而吐槽或放弃。而这些或多或少都和代码不规范、冗余,apk体积过大有关,因此apk瘦身在android应用的性能优化上来说也是不可绕过的一部分。接下来我们就来聊聊apk瘦身的那些事儿。
Apk Analyzer:
为了更好、更直观的说明apk瘦身的必要性,我特意找了一个以前无用的代码,接下来我们就给这个代码瘦个身。
Apk analyzer是android studio2.2之后自带的apk分析工具,它能够通过apk文件查看各个目录及文件的大小,可以查看apk版本信息、也可以直接比较新旧版本apk,直观的发现文件大小变化。我们可以通过点击Android studio菜单栏Build -> Analyze Apk...弹窗选择我们需要分析的apk。打开后视图如下:
![apk analyzer](https://i-blog.csdnimg.cn/blog_migrate/c222f6ebdbe4f6feae3c4f65f1e5e6b2.png)
通过上图可知,这个apk大小为172.6MB,通过Google play压缩大小为121.1MB,其中lib、assets、res是体积过大的主要文件夹。因此该apk的优化思路就是尽量去除无用的资源及jar包。接下来我们可以开始进行瘦身了,最后再通过Apk Analyzer来做一个前后比较,这样我们就可以很直观的发现是哪些地方瘦下去了。
Lint:
Lint是android开发者们常用的工具之一,也是Android Studio自带的代码扫描工具。它可以识别出项目中那些没有被任何代码所引用的资源文件,硬编码,重复的图标等一系列的问题。我们可以通过点击Android Studio菜单栏中的Analyze->Inspect Code...弹窗选择要扫描的具体范围然后进行扫描。我们对项目的全部内容进行扫描,结果如下图所示。
![扫描结果展示](https://i-blog.csdnimg.cn/blog_migrate/307f4b1273c6835dfbf1cb3aab2ce04d.png)
左边是问题的列表,右边是错误的类型、文件的检测报告,也提供了一些操作建议。一般情况下我们可能只想直接清除无用资源而不关心扫描的问题。那么我们可以点击Analyze->Run Inspection by name弹窗直接搜索"unuser resources"无用资源来进行扫描。扫描结果如下,点击Remove All Unused Resources来清除无用资源。
我们也可以在Gradle中配置lintOptions来更好的使用Lint。
lintOptions { //关于Lint的Gradle配置
// 关闭对您指定的问题ID的检查。
disable 'TypographyFractions','TypographyQuotes'
// 打开对您指定的问题ID的检查。
enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
// 要仅对问题ID的子集启用检查并忽略所有其他问题,请改为使用“ check”属性列出问题ID。
// 此属性将覆盖您使用上述属性启用或禁用的所有问题ID。
check 'NewApi', 'InlinedApi'
// 如果设置为true,则关闭lint的分析进度报告。
quiet true
// 如果设置为true(默认值),则在发现错误时停止构建。
abortOnError false
// 如果为true,则仅报告错误
ignoreWarnings true
}
减小libs体积:
在NDK开发过程中往往会加入一些.so动态库,它们会被添加到“x86”、“x86_64”,“armeabi”、“armeabi-v7a”和“arm64-v8a”下,在实际的引用中应用程序会根据手机的cpu来选择对应文件夹下面的so库去执行。因此优化思路就是去除那些不会被cpu所调用的动态库文件。“x86”和“x86_64”通常在android模拟器上被使用,它们的区别在于是32位还是64位系统,“armeabi”针对的是普通的或旧的arm cpu,而"armeabi-v7a"则针对有浮点预算和高级扩展功能的arm v7 cpu。“arm64-v8a”是针对64位arm。了解了这些之后,我们可以根据应用的受众群体来合理的配置动态库。我们这里可以只支持"armeabi-v7a"即可,删除其他所有的文件夹及文件夹下的so库(记得备份哟),并在Gradle下配置abiFilters,如下所示:
defaultConfig {
......
ndk { //设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
abiFilters "armeabi-v7a"
}
}
图片和动画的优化处理:
瘦身无非就两点,一个是“删除”、一个是“压缩”。通过上面的方式该删除的也都删的差不多了,接下来就是压缩的事儿了。首先我们可以将大部分图片格式替换成webp格式。webp是2010发布的,目的是为了减少文件大小,但达到与jpeg格式相同的图片质量。那么我们该如何将PNG、JPG等格式的图片转化为webp格式的文件呢。其实Android Studio就支持转webp格式,选择图片资源右键,找到Convert to webp...即可转为为webp格式的图片。转换后对比如下,这张图片从3.5KB缩小到了1.8KB,效果显著。
其次是尽量不要使用帧动画,由于帧动画的特殊性会占用大量的空间,因此在项目中能避免就避免使用帧动画,有时候交给UI解决会比我们自己处理好很多。最后有些图片资源也可以交由服务器存储,在必要时再下载使用。
其他:
有时候我们会引用一些第三方的jar包,但是又只用了里面一小部分功能,那么这时候我们可以考虑下载并引用完整代码来替换jar包,同时删除我们不需要的代码,只保留需要的功能代码即可,当然删减别人的代码这并不容易,因此我们可以在所有的优化瘦身完成之后再考虑优化这些第三方jar包。
如果项目中只需要支持少量的语言,我们也可以在Gradle中配置:
defaultConfig {
......
resConfigs "zh"
}
另外我们还可以设置shrinkResources为true来在编译过程中删除所有未被使用到的资源文件,其优点是不需要我们删除物理资源。要使得shrinkResources起作用,必须保证minifyEnabled 为true,因此其配置如下:
buildTypes {
release {
minifyEnabled true
shrinkResources true //删除所有未被使用到的资源文件
}
}
总结:
最后我们再通过apk analyzer的比较功能来比较一下瘦身前后的apk的体积变化。
![apk瘦身前后对比图](https://i-blog.csdnimg.cn/blog_migrate/5a76cd9452204ebd851330b64b4beb45.png)
从上图我们可以看到经过一系列瘦身之后的apk总大小减少了65.9MB,减小了38.2%,效果还是很显著的。当然这里lib中的一些第三方jar包,assets中的资源还可以进一步优化压缩,我这里就没有一一演示了。