Android性能优化—apk瘦身

1.代码
2.资源方面
3.动态库

APK的结构

包含以下目录:

  • assets/: 包含了应用的资源,这些资源能够通过AssetManager对象获得。
  • lib/: 包含了针对处理器层面的被编译的代码。这个目录针对每个平台类型都有一个子目录,比如armeabi, armeabi-v7a, arm64-v8a, x86, x86_64和mips。
  • res/: 包含了没被编译到resources.arsc的资源。
  • META-INF/: 包含CERT.SF和CERT.RSA签名文件,也包含了MANIFEST.MF文件。(译注:校验这个APK是否被人改动过)

包含以下文件:

  • classes.dex: 包含了能被Dalvik/Art虚拟机理解的 dex 文件格式的类。
  • resources.arsc: 包含了被编译的资源。该文件包含了res/values目录的所有配置的 xml 内容。打包工具将 xml 内容编译成二进制形式并压缩。这些内容包含了语言字符串和styles,还包含了那些内容虽然不直接存储在resources.arsc文件中,但是给定了该内容的路径,比如布局文件和图片。所以又叫 资源映射表
  • AndroidManifest.xml: 包含了主要的Android配置文件。这个文件列出了应用名称、版本、访问权限、引用的库文件。该文件使用二进制 xml 格式存储。(译注:该文件还能看到应用的minSdkVersion, targetSdkVersion等信息)

使用SVG矢量图

SVG导入

SVG(Scalable Vector Graphics),可缩放矢量图。SVG不会像位图一样因为缩放而让图片质量下降。优点在于可以减小APK的体积(比如如果使用png图片,则需要在drawable和drawable-xhdpi等目录下放置多套分辨率不同的图片,否则png图片会因为缩放而变得模糊)。常用于简单小图标,官方建议一般图片小于200*200时用SVG,当图片较大时SVG图片绘制时间会较长。对于app的启动页的背景图这种大图片,就不能使用SVG,可以使用webp图片来减小图片大小。

svg是由xml定义的,标准svg根节点为<svg>

Android中只支持 <vector>,我们可以通过 vector 将svg的根节点 <svg> 转换为 <vector>

在Android Studio中打开工程,在res目录中点击右键 -> new -> Vector Asset
在这里插入图片描述

在这里插入图片描述

SVG批量转换

如果有多个svg需要转换为android的vector,则可以通过第三方工具 svg2vector 进行批量转换。

执行转换命令:

java -jar svg2vector-cli-1.0.0.jar -d . -o a -h 20 -w 20

-d 指定svg文件所在目录
-o 输出android vector图像目录
-h 设置转换后svg的高
-w 设置转换后svg的宽

不支持的SVG

如果 SVG 文件包含不受支持的功能,将在 Vector Asset Studio 的底部显示一个错误提示,如图:
在这里插入图片描述
不支持的功能举例:
滤镜效果:不支持投影,模糊和颜色矩阵等效果。
文本:建议使用其他工具将文本转换为形状。

矢量图向后兼容

Android 5.0(API 21)之前的版本不支持矢量图,使用 Vector Asset Studio 有两种方式适配:生成PNG和使用支持库。

方式一:生成 png 格式的图片

Vector Asset Studio 可在构建时 针对每种屏幕密度将矢量图转换为不同大小的位图,在 build.gradle 中配置如下:

SVG 适用于 Gradle 插件1.5 及以上版本;

android{
defaultConfig{
// 5.0(API 21)版本以下,将svg图片生成指定维度的png图片
generatedDensities = [‘xhdpi’,‘xxhdpi’]
}
}

方式二:支持库

在 build.gradle 中配置如下,适用于 Gradle 插件2.0及以上版本:
android{
// Gradle Plugin 2.0+
defaultConfig{
// 利用支持库中的 VectorDrawableCompat 类,可实现 2.1 版本及更高版本中支持 VectorDrawable
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
// 支持库版本需要是 23.2 或更高版本
compile ‘com.android.support:appcompat-v7:23.2.0’
}

这时,使用矢量图必须使用 app:srcCompat 属性,而不是 android:src属性,如下:
在这里插入图片描述

矢量图颜色修改

我们是可以单独修改矢量图某一部分的颜色的,如图:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

Tint着色器

虽然我们前面说了,可以直接在 xml 文件中修改矢量图的颜色,但是并不建议直接修改,我们一般让矢量图为黑色,然后用 Tint 着色器去修改矢量图的颜色。

修改颜色:
在这里插入图片描述
那如果我们想实现一个点击效果呢?

Tint着色器–点击变色

创建两个选择器,然后正常使用即可。

drawable 选择器 battery_selector.xml
在这里插入图片描述

color 选择器 battery_tint_selector.xml
在这里插入图片描述
使用
在这里插入图片描述

ABI–应用二进制接口

早期的Android系统几乎只支持ARM v5的CPU架构,而现在你知道它支持多少种了吗?7种!

Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。

ABI 是应用程序二进制接口简称(Application Binary Interface),定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。

在Android 系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,arm64-v8a,x86,x86_64,mips,mips64。

ABI Supported Instruction Set(s) Notes
armeabi ARMV5TE and later,Thumb-1 No hard float
armeabi-v7a armeabi,Thumb-2,VFPv3-D16,Other,optional Incompatible with ARMv5,v6 devices
arm64-v8a AArch-64
x86 x86(IA-32),MMX,SSE/2/3,SSSE3 No support for MOVBE or SSE4
x86_64 x86-64,MMX,SSE/2/3,SSE3,SSE4.1,SSE4.2,POPCNT
mips MIPS32r1 and later
mips64 MIPS64r6

各版本分析如下:

  • mips / mips64:极少用于手机可以忽略
  • x86 / x86_64:x86 架构的手机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码工具,实现 对 arm .so 的兼容,再考虑 x86 1% 以下的市场占有率,x86 相关的两个 .so 也是可以忽略的
  • armeabi:ARM v5 这是相当老旧的一个版本,缺少对浮点数计算的硬件支持,在需要大量计算时有性能瓶颈
  • armeabi-v7a:ARM v7 目前主流版本
  • arm64-v8a:64位支持

ps:ARM v8的相关信息:

ARM公司自己本身并没有64位芯片设计技术,在2011年11月,他是通过了收购MIPS64处理器架构的部分技术使用权,再结合ARM的一些特性设计出来的。也就是说:MIPS、ARM、X86三大架构中,唯一没有64位技术的ARM,通过收购MIPS的形式得到了64位。

所谓的ARMv8架构,就是在MIPS64架构上增加了ARMv7架构中已经拥有的的TrustZone技术、虚拟化技术及NEON advanced SIMD技术等特性,研发成的。

64位ARMv8架构中包含两个执行状态:AArch32(也就是我们常说的ARMv7)和AArch64(ARMv8)。AArch64执行状态针对64位处理技术,引入了一个全新指令集A64(也就是基于收购的MIPS64架构),而AArch32执行状态将支持现有的ARM指令集。所以64位的ARM处理器中同时包含着32位的ARMv7和64位的ARMv8两种架构。因此:看到这里,你一定明白了,ARM64位处理器和电脑的64位处理器是两个截然不容的概念,他并不是64位就能原生向下兼容32位程序,而是通过64位处理器中集成的32位架构来运行32位程序。说得通俗点,它不是以64位形态来运行32位程序,而是以32位的形态运行32位程序的。

由于目前新出的64位处理器包含两个架构,而且制程技术没有提升(28nm),同时在手机与平板上,芯片面积有着严格的限定,不能过分增加,这导致64位ARM处理器平均分配到每个架构的晶体管数量锐减,也就是说从64位处理器中的32位架构方面,对于同规格的32位处理器而言,不但没有提高,性能反而是一定规模下降的。但处理器厂家又必须给消费者一个交代,以更好的推广64位,所以厂家就必须在其他方面提升性能,以弥补CPU的晶体管数量减少带来的损失。比如:更换性能更强的GPU、提升内存带宽、多核心虚拟单颗核心提升单核性能、联合跑分软件商修改跑分权重(提升GPU分数,降低CPU分数的权重)等等。这样,扬长避短,最终到达消费者手里,用跑分软件一跑,确实有提升,用户开心,厂家腰包也鼓了。

综上所述,ARM64位处理器从严格意义来说,叫它ARM32+64更加贴切,他相对于ARM32位处理器,有倒退的地方,也有进步的余地,但正因为倒退激起了ARM进取的决心,让它大刀阔斧的向前变革,不得不说也算一种进步。但ARM64在的手机上真的有用吗?我只能说,目前确实没啥用,但今后或许有。

谷歌官方曾说,安卓很早前就支持64位了,这话不假,从Android4.0到Android4.4,安卓系统都支持64位的硬件,但是这仅仅表示底层驱动支持64位,能运行在64位的硬件之上,仅此而已。然而,上层运行软件的,无论是Dalvik的虚拟机,还是ART虚拟机都是32位的。也就是说,只要你的手机系统是Android4.0—4.4,即便你的处理器是64位,也只能在32位虚拟机下运行32位程序,就算真的64位程序摆在你眼前,也无法安装。

Android L开始才真正支持32位和64位的ART虚拟机,配合上64位处理器,名正言顺的运行64位软件。但是问题又来了,没有软件商 愿意开发64位程序。

ARMv8是一套不错的指令集,它既支持未来的64位程序,也向下兼容现有32位程序。有了ARMv8的支撑,以后的64位手机操作系统,如Android L 64bit都可以简单、高效地支持现有的32位App,你不用担心兼容性问题。

大小端

大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。

例如这样一个数据:0x11223344 转为二进制为 00010001 00100010 00110011 01000100

大端存储后 我们看到的就是 00010001 00100010 00110011 01000100 即 16进制的 11 22 33 44

小端存储后 我们看到的就是 01000100 00110011 00100010 00010001 即 16进制的 44 33 22 11

现阶段状况

目前Intel的80x86系列芯片是唯一还在坚持使用小端的芯片,ARM芯片默认采用小端,但可以切换为大端;而MIPS等芯片要么采用全部大端的方式储存,要么提供选项支持大端——可以在大小端之间切换。另外,对于大小端的处理也和编译器的实现有关,在C语言中,默认是小端(但在一些对于单片机的实现中却是基于大端,比如Keil 51C),Java是平台无关的,默认是大端。在网络上传输数据普遍采用的都是大端

猜你喜欢

转载自blog.csdn.net/yzpbright/article/details/109276599