背景
对于Android来说,为了方便开发,一方面方便资源的管理,代码的可读性,另外一方面方便适配,Android实现了资源和代码分离。要想做的这一点需要解决一下几个问题:
- 简单编程
- 方便适配(根据不同设备环境选择不同资源加载)
- 加快资源查找速度
- 减少空间占用
针对简单编程方面,Android对资源进行了编序,编程中使用R.type.id 来查找相应资源,所以要在对资源的编译过程中对资源排序,来生成R.java文件,对资源id进行排序,这样大大简化了变成。
方便适配方面主要做的工作就是要在不同的设备环境下选择不同的资源来加载。比如一个叫icon的drawable资源,可以使用不同大小的图片放在drawable,drawable-hdpi, drawable-xxhdpi文件夹下面,我们编程的时候是需要通过R.drawable.icon来加载资源,系统会根据屏幕的密度来自动选择合适的drawable文件夹下的icon资源来进行加载,这其实也大大的简化了应用开发者的编程工作。
加快资源查找速度 和 减少空间占用发面,自然就是要在索引文件的结构上面做文章。
所以对于Android资源索引来说最主要的工作就是对重复的资源进行合并压缩, 对资源进行统编址,快速的配置信息查找能力,以及设计紧凑的文件格式。
对于Android资源的统一编址,Android将资源id分为三部分,package_id, type_id 和 index, 类型包括如下几种assets,res,animator,anim,color,drawable,layout,menu,raw,values,xml。不同的package使用不同的package_id,不同的type使用不同的type_id, 对相同type下的不同资源进行编码,生成不同的index。
对于资源的压缩其实主要就是对重复字符串的合并索引。字符串的合并包含三部分,第一部分是对文件路径的索引,如drawable-xxxhdpi/icon.png资源。 但二部分是对value类型的资源名称进行索引。第三部分则是对xml资源的编译索引。怎么理解value类型的资源和文件类型的资源呢。 上面说的11种资源中values和color类型的资源就是value资源,它不是问家类型的资源,而其他九种资源则都是文件类型的资源。 对于文件类型的资源,如果是xml资源,就需要对xml资源进行编译索引来减少大小。values类型的资源子需要把xml中的信息进行提取索引就可以了。
对于怎样设计一个紧凑的索引文件格式呢,我们来看下资源索引后生成的resource.arsc文件格式。 这里要说明 resource.arsc中包含的信息,对于value类型的资源,resource.arsc主要描述了它的名字,值以及不同配置信息。对于文件类型的资源,resource.arsc则描述了它的文件路径以及配置信息。
下面来看下resource.arsc的格式:
我们从宏观到微观来看下文件的格式:
-
头部
size描述了整个问家的大小。
packageCount描述了该资源文件索引了几个包的信息。 -
valueStrings是一个字符串池类型的数据结构,为了尽可能的压缩字符串资源,一个resource.arsc会将所有包的值信息进行合并索引。 关于字符串池请参考aapt字符串池一文。 另外什么是values呢,对于一个资源,它有两部分,分别是名称和值, 这里valueStrings部分存储的就是所有包的值。
-
package: 这部分包含了多个包信息。
下面我们展开来看包的信息,包含如下几部分:
- 头部:
id:package_id(资源id分为三部分,第一部分就是package_id)。
name:包名。
typeStrings指向后面的资源类型字符串池。
keyStrings指向后面的资源名称字符串池。 - typeStrings:资源类型字符串池,包含了该包下所有类型名称。
- keyString:资源名称字符串池,包含了该包下所有的资源名称。
- typeinfos: 多个typeinfo,每个typeinfo代表该包下的一个类型的资源信息。
下面展开来看类型信息: