引言
? 有那么一句话 <u>“一百遮百丑,一胖毁所有”</u> ,这句话用在我们开发的应用程序上也不为过。为什么会这样说呢?
1.应用程序如果太大,用户下载耗时比较久,占用的流量也大 ,安装速度也就慢,这样用户很容易放弃使用;
2.这么胖的应用程序在运行过程中需要加载的资源和程序都很多,会导致加载速度慢,影响用户使用体验;
3.胖的应用也会在后续的项目维护中造成比较大的麻烦,例如:胖会引起比较多的疾病一样;
? 看来我们对自己开发的应用程序制定一个减肥方案是有必要的,但是在制定方案之前,我们就得像医生一样,对其的构成和胖的原因进行全面的掌握,然后才知道如何制定减肥方案。
1)先来了解一下应用程序的组成结构:
assets目录: 用于存放需要打包到APK中的静态文件,不参与编译,仅拷贝,可以使用AssetManager来检索这些资源;
res目录: 包含未编译到resources.arsc文件中的资源,如:图片,音视频文件等;
resources.arsc: 包含已经编译的资源,如anim 、array、String 、color、raw、style、xml、attr、drawable、menu等等;
lib目录: 包含用于特定处理器软件层的编译的代码,也就是兼容不同平台的类库,常见的有:armeabi,armeabi-v7a ,arm-v8a ,x86,x86_64 和mips;
classes.dex,classes2.dex,classes3.dex: 这些文件包含的就是编译后生成虚拟机认识的dex文件格式的类;
META_INF/: 包含的是签名文件(CERT.SF, CERT.RSA).清单文件MAINFEST.MF,已经一库文件的应用索引
AndroidManifest.xml: 包含核心的Android清单文件,有应用名称,版本,访问权限和应用哭等
分析“胖”的起因:
- 将apk包修改后缀为.zip 文件,解压后查看
- 使用android studio自带的Analyze APK工具(菜单Build---> Analyze APK--->选择你要分析的apk ,或者直接在android studio工程中直接双击你要分析的apk)
- Analyze App Size 插件(安装插件后就可以了,不过笔者在4.1.1的android studio上没有使用成功)
2)“减肥”方案
2.1 资源缩减减肥法
在你应用的build.gradle文件中,添加如下的配置:
android{
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
资源缩减器shrinkResources在Gradle打包的时候可以自动忽略未使用的资源,但是他必须配合minifyEnabled才能发挥出来,代码缩减器minifyEnabled移除所有的代码后,资源缩减器才能知道哪些资源继续使用。
2.2 使用Lint静态代码分析器减肥法
菜单Analyze--->选择Run inspection by name ,然后会弹出如下图:(输入unused...)--->选择module或project ,lint 就开始帮你分析了。。。。
分析完成后,会展示在Inspection Results的窗口中,如下所示:
点击左侧的一个文件后,
注意:
- 不会扫描assets文件夹下的资源,
- 不会扫描通过反射应用的资源或已链接至应用的库文件
- 最后的删除是直接删除文件
2.3 一键移除无用资源减肥法
菜单Refactor--->Remove Unused Resource...---->选择preview 来查看有哪些资源,如下图:
确保资源是确实没有使用,点击Do Refactor 直接移除,但是这个方式有个严重的问题就是针对动态获取资源id的方式会被认为没使用过,从而导致删除会引起错误,那么我们可以用下面的方法来解决:
在res/raw/文件夹中新建一个keep.xml的文件,该文件用来声明哪些资源要保留,哪些资源要舍弃。该文件是不会打包的apk中的。如下:
<?xml version="1.0" encoding="utf-8">
<resources xmlns:tools="http://schemas.android.com/tools"
<!--声明保留的资源:多个资源用逗号隔开-->
tools:keep="@layout/aaaaaa,@layout/bbbbbb,@drawable/ccccc"
<!--声明放弃的资源-->
tools:discard="@layout/ddddd"/>
以上资源缩减器只会删除代码没有引用的资源,但是他不会溢出用于不同设备配置的备用资源,我们可以使用grdle插件的资源配置属性溢出不需要的备用资源。比如我们的语言资源库,我们通过上面的分析器可以看到字符串资源包含了很多国家的语言,但是我们只需要其中的一两个语言的话,我们可以如下做:
android{
//....
defaultConfig{
//......
resConfigs "zh","en"
}
}
//这样就会只保存中文、英文、默认三个语言资源
2.4 动态库打包配置减肥法
android{
defaultConfig{
ndk {
//选择要添加的对应cpu类型的.so库。
abiFilters 'armeabi', 'x86', 'mips', "armeabi-v7a"
// 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
}
}
}
我们在集成第三方库的时候,有些提供了全平台的cpu架构,我们就需要像上面一样添加很多库,但是在android系统中,每一个CPU架构对应一个ABI ,目前支持的有armeabi-v7a ,arm64-v8a ,x86等等。目前市场上的手机设备基本上都是arm架构了,armeabi-v7a 几乎能兼容所有的arm设备,所有我们可以修改上面的配置如下:
android{
defaultConfig{
ndk {
//选择要添加的对应cpu类型的.so库。
abiFilters "armeabi-v7a"
// 还可以添加 'x86', 'x86_64', 'mips', 'mips64','armeabi', 'x86', 'mips',
}
}
}
这样就只会将armeabi-v7a的动态库打包进apk ,这样可以缩写apk的大小。
? 但是针对一些arm64的设备,我们用armeabi-v7a也可以兼容,但是性能方面就不如arm64的库,这样我们针对不同的设备可以提供不同架构的apk来安装。如下来实现:
//方案1
flavorDimensions "default"
productFlavor{
arm32{
dimension "default"
ndk{
abiFilters "armeabi-v7a"
}
}
arm64{
dimension "default"
ndk{
abiFilters "arm64-v8a"
}
}
}
//方案2
splits{
abi{
enable true
reset()
include "armeabi-v7a", "arm64-v8a"
universalApk true //是否将所有的so打包到一个apk中
}
}
2.5 矢量图减肥法
? 在我们的app中图片资源往往占用的空间都比较大,那么对这类图片资源的减肥能快速体现效果的时候。下面我们就分情况来处理一下:
? 1)使用webp格式的图片来替换jpg ,png格式的图片
? 选择你要减肥的图片,点击右键,快捷菜单中选择convert to webp ,开始转换,如下图:
点击“OK”,进入效果展示,如下图:
? 可以看到我们这样就可以将一张5.2kb的图片转换为852byte大小的webp格式的图片,同样我们还可以调整Quality,然后finish按钮,这样就将我们需要优化的图片转换好了。
? 2)使用矢量图
? 矢量图可以创建与屏幕分辨率无关的图标和其他可伸缩的媒体,在android中以VectorDrawable对象的形式来表示,不过系统在渲染每一个VectorDrawable对象的时候需要花费大量的时间,所有建议尽在小图片时使用这些矢量图。
assetType: 可以选择系统的,可以加在本地的SVG ,PSD图
name可以定义为自己需要的名字。
? 点击next---> 选择存放的目录---finish, 这样一张矢量图就创建成功了。
?
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/vector"
tools:ignore="MissingConstraints"/>
? 给矢量图添加颜色:
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:tint="#ff0000"
android:src="@drawable/vector"
tools:ignore="MissingConstraints" />
? 在selector中使用:
<!--定义selector:记得要放在color文件夹中作为颜色选择器-->
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorAccent" android:state_pressed="true"/>
<item android:color="@color/colorPrimary"/>
</selector>
<!--在imageView中使用: 用定义的颜色selector替换tint中的固定值即可-->
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:tint="@color/selector"
android:src="@drawable/vector"
tools:ignore="MissingConstraints" />
? 3)对于一些启动页,引导页等比较大的图片,建议使用jpg格式
好了,以上就是笔者工作中用过的一些减肥方法,如后续有更好的再来完善了。。。。。。