赞
踩
Android应用程序主要由两部分内容组成:代码和资源。资源主要就是指那些与UI相关的东西,例如UI布局、字符串和图片等。代码和资源分开可以使得应用程序在运行时根据实际需要来组织UI。这样就可使得应用程序只需要编译一次,就可以支持不同的UI布局。这种特性使得应用程序在运行时可以适应不同的屏幕大小和密度,以及不同的国家和语言等。
Android应用程序资源可以分为两大类,分别是assets和res:
一、assets
assets类资源放在工程根目录的assets子目录下,它里面保存的是一些原始的文件,可以以任何方式来进行组织。这些文件最终会被原装不动地打包在apk文件中。如果我们要在程序中访问这些文件,那么就需要指定文件名来访问。例如,假设在assets目录下有一个名称为filename的文件,那么就可以使用以下代码来访问它:
AssetManager am= getAssets();
InputStream is = assset.open("filename");
二、res
res类资源放在工程根目录的res子目录下,它里面保存的文件大多数都会被编译,并且都会被赋予资源ID。这样我们就可以在程序中通过ID来访问res类的资源。res类资源按照不同的用途可以进一步划分为以下9种子类型:
1.animator。
这类资源以XML文件保存在res/animator目录下,用来描述属性动画。属性动画通过改变对象的属性来实现动画效果,例如,通过不断地修改对象的坐标值来实现对象移动动画,又如,通过不断地修改对象的Alpha通道值来实现对象的渐变效果。
2.anim。
这类资源以XML文件保存在res/anim目录下,用来描述补间动画。补间动画和属性动画不同,它不是通过修改对象的属性来实现,而是在对象的原来形状或者位置的基础上实现一个变换来得到的,例如,对对象施加一个旋转变换,就可以获得一个旋转动画,又如,对对象实施一个缩放变换,就可以获得一个缩放动画。从数学上来讲,就是在对象的原来形状或者位置的基础上施加一个变换矩阵来实现动画效果。注意,在动画的执行过程中,对象的属性是始终保持不变的,我们看到的只不过是它的一个变形副本。
3.color。
这类资源以XML文件保存在res/color目录下,用描述对象颜色状态选择子。例如,我们可以定义一个选择子,规定一个对象在不同状态下显示不同的颜色。对象的状态可以划分为pressed、focused、selected、checkable、checked、enabled和window_focused等7种。
4.drawable。
这类资源以XML或者Bitmap文件保存在res/drawable目录下,用来描述可绘制对象。例如,我们可以在里面放置一些图片(.png, .9.png, .jpg, .gif),来作为程序界面视图的背景图。注意,保存在这个目录中的Bitmap文件在打包的过程中,可能会被优化的。例如,一个不需要多于256色的真彩色PNG文件可能会被转换成一个只有8位调色板的PNG面板,这样就可以无损地压缩图片,以减少图片所占用的内存资源。
5.layout。
这类资源以XML文件保存在res/layout目录下,用来描述应用程序界面布局。
6.menu。
这类资源以XML文件保存在res/menu目录下,用来描述应用程序菜单,例如,Options Menu、Context Menu和Sub Menu。
7.raw。
这类资源以任意格式的文件保存在res/raw目录下,它们和assets类资源一样,都是原装不动地打包在apk文件中的,不过它们会被赋予资源ID,这样我们就可以在程序中通过ID来访问它们。例如,假设在res/raw目录下有一个名称为filename的文件,并且它在编译的过程,被赋予的资源ID为R.raw.filename,那么就可以使用以下代码来访问它:
Resources res = getResources();
InputStream is = res .openRawResource(R.raw.filename);
8.values。
这类资源以XML文件保存在res/values目录下,用来描述一些简单值,例如,数组、颜色、尺寸、字符串和样式值等,一般来说,这六种不同的值分别保存在名称为arrays.xml、colors.xml、dimens.xml、strings.xml和styles.xml文件中。
9.xml。
这类资源以XML文件保存在res/xml目录下,一般就是用来描述应用程序的配置信息。
注意,上述9种类型的资源文件,除了raw类型资源,以及Bitmap文件的drawable类型资源之外,其它的资源文件均为文本格式的XML文件,它们在打包的过程中,会被编译成二进制格式的XML文件。这些二进制格式的XML文件分别有一个字符串资源池,用来保存文件中引用到的每一个字符串,包括XML元素标签、属性名称、属性值,以及其它的一切文本值所使用到的字符串。这样原来在文本格式的XML文件中的每一个放置字符串的地方在二进制格式的XML文件中都被替换成一个索引到字符串资源池的整数值。这样做有两个好处:
文件占用更小。例如,假设在原来的文本格式的XML文件中,有四个地方使用的都是同一个字符串,那么在最终编译出来的二进制格式的XML文件中,字符串资源池只有一份字符串值,而引用它的四个地方只占用一个整数值。
解析速度更快。由于在二进制格式的XML文件中,所有的XML元素标签和属性等值都是使用整数来描述的,因此,在解析的过程中,就不再需要进行字符串解析,这样就可以提高解析速度。
还有另外一个地方需要注意的是,每一个res资源在编译的打包完成之后,都会被分配一个资源ID,这些资源ID被终会被定义为Java常量值,保存在一个R.java文件中,与应用程序的其它源文件一起被编译到程序中,这样我们就可以在程序或者资源文件中通过这些ID常量来访问指定的资源。
三、总结
除了assets和res/raw资源被原装不动地打包进APK之外,其它的资源都会被编译或者处理。
除了assets资源之外,其它的资源都会被赋予一个资源ID。
打包工具负责编译和打包资源,编译完成之后,会生成一个resources.arsc文件和一个R.java,前者保存的是一个资源索引表,后者定义了各个资源ID常量。
应用程序配置文件AndroidManifest.xml同样会被编译成二进制的XML文件,然后再打包到APK里面去。
应用程序在运行时通过AssetManager来访问资源,或通过资源ID来访问,或通过文件名来访问。
在项目文件夹的gen文件夹里面有个R.java,我们平常引用的资源主要引用这个类的变量。注意:R类是自动生成的,并且它不能被手动修改。当资源发生变动时,它会自动修改。
Android资源除了assets目录是与res同级外,其它资源均被放在res/目录下面,该目录下面的资源文件夹并不是随意命名的,需要遵循严格的规范,否则编译生成R.java过程中会报类似“invalidresource directory name **”的错误提示,并且导致R.java自动生成失败。每个文件夹中存放的文件类型不仅有规定,而且对文件内容也是有严格要求的,曾经将一个定义布局的spinner.xml文件放置在res/values,结果就报“Invalid start tag *Layout spinner.xml”错误,并导致R.java没有生成;将该布局文件放置在res/color下面,虽然没有报错,但是原本的布局文件,不再是正确生成为形如“R.layout.spinner”的布局资源,而是生成为了“R.color.spinner”的颜色资源索引,具体如下所示
布局文件放置正确的R.java中代码
public static final class layout {
public static final int autocomplete=0x7f030000;
public static final int spinner=0x7f03000d;
}
布局文件放置错误的R.java中代码
public static final class color {
public static final int solid_blue=0x7f050001;
public static final int spinner=0x7f050004;
}
另外当一种资源定义XML文件放在不对应的res文件夹下,在可视化环境下,也就不能正确显示和编辑。
通过上述一些特性,我们可以猜测出android的aapt工具的工作原理,先是根据文件夹名来进行对资源文件和XML文件进行不同的解析和编译规则进行解析和编译,ADT工具也是根据具体文件夹名称调用不同的规则来可视化编辑和呈现。
在一个Acitvity或者一个Service中,我们直接this.getResources()方法,就可以获得Reousrces对象。其实Acitivity或者Service本质上就是一个Context,getResources()方法来自Context,而真正实现Context接口是ContextImpl类,所以调用的实际上时ContextImpl类的getResources()方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。