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

android资源和资源ID之间的映射是如何工作的?,android,android-resources,Android,Android Resources,Android通过R.id.XXX找到合适的资源非常神奇 好了,这些资源被编译成二进制格式,那么这种映射逻辑在后台是如何工作的呢 可能它的工作原理如下: 例如,在layout1.xml中,我们得到: <Button android:id="@+id/button1" > 当生成*.apk时,带有的@+id/button1将替换为“0x7f05000b” 因此,当我们呼吁: findViewById(R.id.button1); 虽然ID是一个类似0x7f05000b的数字,但我们

Android通过R.id.XXX找到合适的资源非常神奇

好了,这些资源被编译成二进制格式,那么这种映射逻辑在后台是如何工作的呢

可能它的工作原理如下:

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

<Button android:id="@+id/button1" >
当生成*.apk时,带有的@+id/button1将替换为“0x7f05000b”

因此,当我们呼吁:

findViewById(R.id.button1);
虽然ID是一个类似0x7f05000b的数字,但我们基本上仍然基于ID进行搜索

谢谢

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


例如,如何找到具有资源id的可绘制图片?或者如何使用资源id找到字符串值?

神奇之处在于Eclipse插件及其在应用程序的“gen”文件夹中自动生成的R.java文件。如果查看此文件,您将看到R.xx.XXX中每个XXX的静态映射,其中xx可以是动画、数组、颜色和其他所有资源类型。

如果您对内部实现(设备端)感兴趣,请查看中的loadDrawable()。请参阅hackbod的优秀答案,了解有关


为了了解如何将版面从资源ID的check out.java转换为视图,据我所知,aapt将自动为每个资源生成唯一的ID,并将它们存储在查找表中。此查找表作为“bin/resources.ap_”中的“resources.arsc”文件保存(这只是一个ZIP文件,因此可以使用您喜爱的ZIP查看器随意打开)。查找表也被持久化为R.java,正如您所知,它允许您引用java中的资源

如果你想了解更多关于ARSC文件的信息,我建议你在谷歌上搜索一下,或者查看代码


-Dan

在构建时,aapt工具收集您定义的所有资源(尽管文件中有单独的文件或明确的定义),并为它们分配资源ID

资源ID是一个32位的数字,格式为:PPTTNNNN。PP是资源所在的包;TT是资源的类型;NNNN是该类型中资源的名称。对于应用程序资源,PP始终为0x7f

TT和NNNN值由aapt任意分配——基本上,对于每种新类型,分配并使用下一个可用数字(从1开始);同样,对于类型中的每个新名称,将分配并使用下一个可用编号(从1开始)

因此,如果aapt按照以下顺序处理这些资源文件:

layout/main.xml
drawable/icon.xml
layout/listitem.xml
我们看到的第一种类型是“布局”,因此给定TT==1。该类型下的第一个名称是“main”,因此给定NNNN==1。最终的资源ID是0x7f010001

接下来我们看到“drawable”,因此给定TT==2。该类型的第一个名称是“icon”,因此得到NNNN==1。最终的资源ID是0x7f020001

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

请注意,默认情况下,aapt不会尝试在构建之间保持这些标识符相同。每次资源更改时,它们都可以获得新的标识符。每次构建它们时,都会使用当前标识符创建一个新的R.java,以便代码获得正确的值。因此,您决不能将资源标识符保留在任何可以跨应用程序的不同版本使用的地方

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

您可以使用命令“aapt dump resources”在apk中获取resources.arsc文件的摘要

二进制资源表的格式记录在以下资源数据结构的头文件中:

读取设备上资源表的完整实现如下:


最后一点注意:我最长时间没有使用相对布局,因为许多项需要引用xml文件中更深层的项,而且我不知道如何引用尚未定义的@id/foo

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

在上面
在下面
然后有一天我意识到(duh)你可以在引用中定义一个id;它不必位于带有id的元素中:

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

在上面
在下面

谢谢你的重要提示。我要搜查一下。如果没有更好的答案出现,我会记下你的答案。谢谢。顺便说一句,这些细节在什么地方有记录吗?除了我在这里链接的结构定义之外,实现细节没有记录。顺便说一句,IMHO,“RTFSC”是错误的。源是对规范的解释,可以更改。如果没有规范,那么行为就没有正式定义。阅读源代码只能告诉您作者在编写规范时认为规范的含义。它告诉你现在发生了什么,但不告诉你以后会发生什么。尽管如此,Dianne出色的解释可能会给你你需要知道的东西,并在可预见的未来保持相关性。@edward falk:我认为RTFSC在这里是正确的,因为第一个问题是关于引擎盖下的东西(从来没有正式规范过),而不是API。内部规范是SC:)对XML中字符串和其他值的引用是在生成或运行时解析的吗?
<!-- works -->
<TextView android:layout_above="@+id/foo">above</textview>
<TextView android:id="@id/foo">below</textview>