Android编译资源-resources.arsc

Android编译资源-resources.arsc,android,resources,r.java-file,Android,Resources,R.java File,我试图弄清楚“编译资源”的含义 为了理解这个问题,我做了什么: 我读了很多关于这个问题的文章,但没有找到一个简单的答案。 我读过的最好的一本是: 我的理解是: 据我所知,当我们用ANT(Eclipse)或Gradle(AS)编译我们的项目时。 我们使用一个名为aapt-Android资产打包工具的工具,该工具: 用于为每个资源生成唯一的ID,例如布局、样式等,并将其存储在查找表中。然后,它通过生成两个文件来保持此查找表: 它使用这些唯一的ID生成R.java文件,因此我们可以在编译期间使用jav

我试图弄清楚“编译资源”的含义

为了理解这个问题,我做了什么: 我读了很多关于这个问题的文章,但没有找到一个简单的答案。 我读过的最好的一本是:

我的理解是: 据我所知,当我们用ANT(Eclipse)或Gradle(AS)编译我们的项目时。 我们使用一个名为aapt-Android资产打包工具的工具,该工具: 用于为每个资源生成唯一的ID,例如布局、样式等,并将其存储在查找表中。然后,它通过生成两个文件来保持此查找表:

  • 它使用这些唯一的ID生成R.java文件,因此我们可以在编译期间使用java代码中的资源
  • 它将生成resources.arsc文件,该文件可在resources*.ap_u.文件中找到。 此resources.arsc文件稍后将由apktool打包到apk。
    此arsc文件格式是设备在运行时可以轻松映射和解析的格式
  • 例如: 简单地说:假设我的activity_main.xml中有以下内容:

        <TextView android:id="@+id/my_textView"
            android:text="@string/hello_world" 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
    在我的R.java文件中,我将看到:

    public static final int my_textView=0x7f08003f;
    
    在生成的apk上使用:aapt dump resources,我可以看到它包含两行my_textView: ec资源0x7f08003f com.example.lizi.liortest2:id/my_textView:flags=0x00000000 资源0x7f08003f com.example.lizi.liortest2:id/my_textView:t=0x12 d=0x00000000(s=0x0008 r=0x00)

    我不明白的是: 我本以为这个resources.arsc文件不仅包含资源ID,还包含我为视图定义的所有属性,比如android:layout\u width=“wrap\u content”

    因此,现在在运行时,当VM尝试运行
    findViewById(R.id.my_textView)
    它如何知道要获取/创建哪个视图的属性

    我就是不明白它是怎么工作的。。。这个查找表不应该也包含属性数据吗? 这个0x7f08003f号码是什么?(是否表示稍后将映射到存储对象的物理内存的值?

    TL;DR:在android编译器(aapt)的帮助下,xml节点被转换为Java类,相应的xml属性被转换为数字ID。Android运行时使用这些数字ID来实例化类和创建视图

    TL;R 运行此命令以转储二进制xml
    aapt d xmltree apk_文件\u name res/layout/activity\u main.xml
    (aapt可在android sdk目录/build tools/23.0.2/aapt.exe中找到)

    这将显示xml节点(例如
    LinearLayout
    RelativeLayout
    等)及其属性(例如
    android:layout\u width,android:layout\u height
    )及其值。请注意,可以在此处看到常量
    匹配父项(数值
    0xFFFFFF
    -1
    )或
    包装内容(数值
    0xFFFFFE
    -2

    事实上,您可以在apk中的任何其他xml文件上使用此命令,例如,
    AndroidManifest.xml或其他布局文件

    apk文件只是一个zip归档文件,包含所有java类文件(
    classes.dex
    ),所有编译的资源文件和一个名为
    resources.arsc
    的文件。 此
    resource.arsc
    文件包含有关资源的所有元信息。其中一些是

    • xml节点(例如,
      LinearLayout
      RelativeLayout
      等)
    • 属性(例如,
      android:layout\u width
    • 资源
      id
    资源
    id
    指的是apk文件中的真实资源。这些属性在运行时解析为一个值。解析过程在任何重新定向方面都是智能的(
    @dimen/..
    相对于
    4dp
    @color/..
    相对于
    “#FFaabbcc”
    )并返回可用值(dimen
    值的解析方式不同于
    color
    值)

    什么是已编译的XML文件: 编译后的XML文件就是相同的XML文件,资源引用更改为相应的
    id
    。例如,引用
    @string/ok
    将替换为
    0x7f000001
    。此外,
    android
    命名空间中的属性更改为各自的整数值(例如,
    wrap\u content
    更改为
    0xfffffe
    -2

    Android如何在运行时解析资源: 该方法解析已编译的xml文件,并通过实例化xml节点创建视图层次结构。每个xml节点都由一个java类实例化(例如LinearLayout.java、RelativeLayout.java)。为了实例化,充气器解析已编译的xml文件,收集节点的所有属性和类型为的压缩结构。这个
    AttributeSet
    被传递给类构造函数。类构造函数负责遍历
    属性集
    ,并解析每个属性值

    例如,对于包含
    RelativeLayout
    的布局,
    充气机
    布局宽度
    布局高度
    打包到
    属性集
    中,并将其传递给构造器

    在这种情况下,某些属性由解析。其余属性由父级解析。视图的属性
    android:id
    只是另一个属性。充气后,充气器在实例化后将每个视图的id存储在该视图上

    现在回答您的问题
    R.id
    是一个java数组,
    R.id.my_textview
    是该数组中的一个整数。视图
    my_textview
    id
    是这个整数(以0x7f开始)。该方法对该vi执行深度优先搜索
    public static final int my_textView=0x7f08003f;
    
    public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }
    
        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }
    
    public XmlResourceParser getLayout(int id) throws NotFoundException {
        return loadXmlResourceParser(id, "layout");
    }
    
    XmlResourceParser loadXmlResourceParser(int id, String type)
            throws NotFoundException {
        synchronized (mAccessLock) {
            TypedValue value = mTmpValue;
            if (value == null) {
                mTmpValue = value = new TypedValue();
            }
            getValue(id, value, true);
            if (value.type == TypedValue.TYPE_STRING) {
                return loadXmlResourceParser(value.string.toString(), id,
                        value.assetCookie, type);
            }
            throw new NotFoundException(
                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
                    + Integer.toHexString(value.type) + " is not valid");
        }
    }
    
    Use appt for android-sdk (ex:- /build-tools/27.0.3/aapt )
    
     run given script and get resources.arsc file content
    ./aapt dump resources ./debug.apk
    
    Package Groups (1)
    Package Group 0 id=0x7f packageCount=1 name=com.dianping.example.activity
      Package 0 id=0x7f name=com.dianping.example.activity
        type 1 configCount=3 entryCount=1
          spec resource 0x7f020000 com.example.activity:drawable/ic_launcher: flags=0x00000100
          config mdpi-v4:
            resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000000 (s=0x0008 r=0x00)
          config hdpi-v4:
            resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000001 (s=0x0008 r=0x00)
          config xhdpi-v4:
            resource 0x7f020000 com.example.activity:drawable/ic_launcher: t=0x03 d=0x00000002 (s=0x0008 r=0x00)
        type 2 configCount=1 entryCount=1
          spec resource 0x7f030000 com.dianping.example.activity:string/app_name: flags=0x00000000
          config (default):
            resource 0x7f030000 com.dianping.example.activity:string/app_name: t=0x03 d=0x00000003 (s=0x0008 r=0x00)