Android资源和资源ID之间的映射是如何工作的?

Android仅通过R.id.XXX定位适当的资源是不可思议的

AFAIK,资源被编译为二进制格式,那么这个映射逻辑如何工作呢?

也许它是这样的:

例如,在layout1.xml中 ,我们得到:

<Button android:id="@+id/button1" > 

而AAPT将在R.java中生成这个:

 public static final int button1=0x7f05000b; 

* .apk生成时, @ + id / button1被replace为“0x7f05000b”。

因此,当我们呼吁:

 findViewById(R.id.button1); 

我们基本上仍然是基于ID进行search,尽pipeID是0x7f05000b这样的数字。

谢谢!

我真正想知道的是,如何将资源ID整数parsing为资源内容? 换句话说,Android运行时如何以资源id为唯一线索定位资源内容?

例如,如何使用资源IDfind可绘制的图片? 或者如何find一个string值与资源ID?

在构build时,aapt工具会收集您定义的所有资源(虽然是单独的文件或文件中的显式定义),并为它们分配资源ID。

资源ID是一个32位的数字forms:PPTTNNNN。 PP是资源的包装; TT是资源的types; NNNN是该types中的资源的名称。 对于应用程序资源,PP总是0x7f。

TT和NNNN值由aapt任意分配 – 基本上为每种新types分配和使用下一个可用数字(从1开始); 同样对于每个新types的名字,下一个可用的号码被分配和使用(从1开始)。

所以如果我们按照这个顺序处理这些资源文件:

 layout/main.xml drawable/icon.xml layout/listitem.xml 

我们看到的第一种types是“layout”,因此给出TT == 1.该types下的第一个名字是“main”,因此给出NNNN == 1.最终的资源ID是0x7f010001。

接下来我们看到“drawable”,这样就给出了TT == 2.该types的名字是“icon”,这样得到NNNN == 1.最终的资源ID是0x7f020001。

最后,我们看到另一个TT = 1的“布局”。 这有一个新名称“listitem”,以便获取下一个值NNNN == 2.最终的资源ID是0x7f010002。

请注意,默认情况下,aapt不会尝试在构build之间保持这些标识符相同。 每当资源发生变化,他们都可以获得新的标识符。 每次构build时,都会使用当前标识符创build一个新的R.java,以便您的代码获得正确的值。 正因为如此,您不能将资源标识符永久保存在可以在应用程序的不同版本中使用的地方。

一旦编译了资源并分配了标识符,aapt将为您的源代码生成R.java文件,并生成一个名为“resources.arsc”的二进制文件,其中包含所有资源名称,标识符和值(用于来自单独文件,它们的值是.apk文件的path),格式可以在运行时轻松在设备上进行映射和分析。

您可以使用命令“aapt dump resources <path-to-apk>”获取apk中resources.arsc文件的摘要。

二进制资源表的格式在这里的资源数据结构的头文件中被logging:

https://github.com/android/platform_frameworks_base/blob/master/libs/androidfw/include/androidfw/ResourceTypes.h

阅读设备资源表的完整实现在这里:

https://github.com/android/platform_frameworks_base/blob/master/libs/androidfw/ResourceTypes.cpp

如果你对内部实现(设备端)感兴趣,请看Resources.java中的 loadDrawable()。 有关从 资源表中 提取数据的信息,请参阅hackbod的出色答案

要知道布局如何从资源ID转换到View中,请检查LayoutInfater .java

据我所知,aapt会自动为您的每个资源生成唯一的ID并将其存储在查找表中。 这个查找表被保存为位于“bin / resources.ap_”中的“resources.arsc”文件(这只是一个ZIP文件,所以可以随意使用您最喜爱的ZIP查看器打开)。 查找表也作为R.java持久化,正如你所知,它允许你用Java引用你的资源。

如果您想了解更多有关ARSC文件的信息,我会build议您使用Googlesearch,或查看http://code.google.com/p/android-apktool/的代码。;

-担

最后一个注意事项:最长的时间,我没有使用相对布局,因为许多项目需要引用进一步在xml文件中的项目,我不知道如何引用尚未定义的@ id / foo然而。

 <!-- doesn't work --> <TextView android:layout_above="@id/foo">above</textview> <TextView android:id="@+id/foo">below</textview> 

然后有一天我意识到(杜)你可以在参考文献中定义一个id; 它不一定要在承载id的元素中:

 <!-- works --> <TextView android:layout_above="@+id/foo">above</textview> <TextView android:id="@id/foo">below</textview> 

Eclipse的插件和R.java文件是在应用程序的“gen”文件夹中自动生成的。 如果你仔细查看这个文件,你会看到R.xx.XXX中每个XXX的静态映射,其中xx可以是animation,数组,颜色和其他任何资源types。