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

smw*_*dia 71 android android-resources

Android的神奇之处在于只通过R.id.XXX找到合适的资源.

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

也许它的工作原理如下:

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

<Button android:id="@+id/button1" >
Run Code Online (Sandbox Code Playgroud)

和AAPT将在R.java中生成:

public static final int button1=0x7f05000b;
Run Code Online (Sandbox Code Playgroud)

当生成*.apk时,@ + id/button1将替换为"0x7f05000b".

因此,当我们打电话时:

findViewById(R.id.button1);
Run Code Online (Sandbox Code Playgroud)

我们基本上仍然根据ID进行搜索,尽管ID是一个像0x7f05000b的数字.

谢谢!

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

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

hac*_*bod 182

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

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

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

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

layout/main.xml
drawable/icon.xml
layout/listitem.xml
Run Code Online (Sandbox Code Playgroud)

我们看到的第一种类型是"布局",因此给出TT == 1.该类型下的第一个名称是"main",因此给出NNNN == 1.最终资源ID为0x7f010001.

接下来,我们看到,这样给予TT == 2名该类型是"图标",这样得到NNNN == 1,最终资源ID是0x7f020001"绘制".

最后我们看到另一个"布局",其中TT == 1和以前一样.这有一个新名称"listitem",因此获取下一个值NNNN == 2.最终资源ID为0x7f010002.

请注意,默认情况下,aapt不会尝试在构建之间保持这些标识符相同.每次资源发生变化时,都可以获得新的标识符.每次构建它们时,都会使用当前标识符创建一个新的R.java,以便您的代码获得正确的值.因此,您必须永远不要将资源标识符保留在可以在应用程序的不同版本中使用的任何位置.

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

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

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

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

  • 顺便说一句,恕我直言,“RTFSC”是错误的。来源是对规范的解释,可以更改。如果没有规范,则行为是正式未定义的。阅读源代码只会告诉您作者在编写规范时认为规范的含义。它会告诉您*现在* 会发生什么,但不会* 稍后* 会发生什么。Dianne 的出色解释仍然可能为您提供您需要了解的内容,并在可预见的未来保持相关性。 (2认同)

Ren*_*eno 7

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

要了解布局是如何从资源ID转换为View的,请查看LayoutInfater .java


Dan*_*Dan 5

根据我的理解,aapt将为您的每个资源自动生成唯一ID,并将它们存储在查找表中.此查找表保存为位于"bin/resources.ap_"中的"resources.arsc"文件(这只是一个ZIP文件,因此可以使用您最喜欢的ZIP查看器打开).查找表也作为R.java保留,如您所知,允许您使用Java引用您的资源.

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

-担