在Android中资源的使用几乎无处不在,layout、string、drawable、raw、style、theme等等都是。


这些资源会在编译过程中被打包进APK中(res文件夹)或者被打包成独立的资源APK包(比如framework-res.apk)。



独一无二的ID即资源索引来方便系统访问。



这些资源索引由Android的工具AAPT(Android Asset Packing Tool)生成的八位十六进制整数型。




中间 02 所在位置值代表资源ID对应的资源的类型,分别是:



02:drawable



03:layout



04:values



05:xml



06:raw



07:color



08:menu



分配resource id的主要逻辑实现是在framework/base/tools/aapt/Resource.cpp 和 ResourceTable.cpp。



现在以Demo为例




资源ID 是一个32bit的数字,格式是PPTTNNNN , PP代表资源所属的包(package) ,TT代表资源的类型(type),NNNN代表这个类型下面的资源的名称。 对于应用程序的资源来说,PP的取值是0×77。



TT 和NNNN 的取值是由AAPT工具随意指定的–基本上每一种新的资源类型的数字都是从上一个数字累加的(从1开始);而每一个新的资源条目也是从数字1开始向上累加的。



注意的是,AAPT在每一次编译的时候不会去保存上一次生成的资源ID标示,每当/res目录发生变化的时候,AAPT可能会去重新给资源指定ID号,然后重新生成一个R.java文件。因此,在做开发的时候,你不应该在程序中将资源ID持久化保存到文件或者数据库。而资源ID在每一次编译后都有可能变化。



一旦资源被编译成二进制文件的时候,AAPT会生成R.java 文件和“resources.arsc”文件,“R.java”用于代码的编译,而”resources.arsc”则包含了全部的资源名称、资源ID和资源的内容(对于单独文件类型的资源,这个内容代表的是这个文件在其.apk 文件中的路径信息)。这样就把运行环境中的资源ID 和具体的资源对应起来了。





对于集成第三方aar包,首先得明白一点,打出来的aar包中是不带R文件的,aar中的资源文件是随着主工程的编译而生成的,例如项目A引用了两个aar,分别为resOne和resTwo,当项目编译完后,R文件的目录结构如图所示:




这两个R文件中放的就是resOne和resTwo两个lib的资源文件ID,测试过程中,将两个moudle中activity的layout名称统一命名为main_activity_one,那么在R中文件中资源ID都为






当唤起其中一个activity时,就会报






标识资源文件ID已经生成了一次,当启动某个acitity时,主端会去找另外一个相同资源ID的layout,从而导致其中的控件无法找到。



  1. 项目中资源ID名字在相同的资源类型中不能命名相同
  2. 集成进来的第三方aar资源文件,命名不能相同
  3. 项目中禁止命名和系统资源名称相同的资源