android resources r.java-file

Recursos compilados de Android-resources.arsc



r.java-file (3)

Estoy tratando de averiguar qué significa "compilar recursos".

Lo que hice para entender este problema:

He leído muchos artículos sobre el tema pero no encontré una respuesta simple. El mejor que he leído fue el siguiente: ¿Cómo funciona la asignación entre los recursos de Android y la identificación de recursos? .

Como lo entiendo

A mi entender, cuando compilamos nuestro proyecto ya sea por ANT (Eclipse) o Gradle (AS). Usamos una herramienta llamada aapt - Android Asset Packaging Tool que: se utiliza para generar ID únicas para cada uno de nuestros recursos, como nuestros diseños, nuestros estilos y más, y almacenarlos en una tabla de búsqueda. Luego persiste esta tabla de búsqueda generando dos archivos:

  1. Genera el archivo R.java con estas ID únicas, por lo que podremos usar nuestros recursos de nuestro código Java durante la compilación.
  2. Genera el archivo resources.arsc que se puede encontrar en el archivo resources * .ap_. Este archivo resources.arsc se empaquetará más tarde con la herramienta apktool a la apk.
    Este formato de archivo arsc es un formato que será fácilmente asignado y analizado por el dispositivo en tiempo de ejecución.

Un ejemplo:

Así que para hacerlo más simple: digamos que tengo esto en mi activity_main.xml:

<TextView android:id="@+id/my_textView" android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" />

Y lo llamo desde mi onCreate usando:

findViewById(R.id.my_textView)

En mi archivo R.java veré:

public static final int my_textView=0x7f08003f;

Utilizando: aapt dump resources en el apk generado puedo ver que contiene dos líneas con my_textView: ec resource 0x7f08003f com.example.lizi.liortest2: id / my_textView: flags = 0x00000000 resource 0x7f08003f com.example.lizi.liortest22 : t = 0x12 d = 0x00000000 (s = 0x0008 r = 0x00)

Lo que no entiendo:

Pensé que este archivo resources.arsc no solo contendrá el ID de recurso sino también todas las propiedades que he definido para la vista, como android: layout_width = "wrap_content".

Así que ahora, durante el tiempo de ejecución, cuando la VM intenta ejecutar findViewById(R.id.my_textView) ¿Cómo sabe qué vista obtener / sus propiedades crear?

Simplemente no puedo entender cómo funciona ... ¿No debería esta tabla de búsqueda contener también los datos de propiedades? ¿Y cuál es este número 0x7f08003f? (¿Debe representar un valor que luego se asignará a la memoria física en la que se almacenará el objeto?)


LayoutInflater infla la vista utilizando cadenas XML. Cadenas XML compiladas en un archivo de recursos como mencionó en su pregunta.

Por favor revise estos fragmentos de código de AOSP:

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(); } }

Resources.getLayout carga el analizador de recursos XML

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"); } }

getValue usa getResourceValue AssetManager y llama loadResourceValue método nativo loadResourceValue . Este método nativo llama al método ResTable de getResource para obtener cadenas XML almacenadas en un archivo de recursos.


TL; DR : Con la ayuda del compilador de Android (aapt), los nodos XML se traducirán a las clases de Java y los atributos correspondientes a las identificaciones numéricas. El tiempo de ejecución de Android funciona con estos identificadores para crear una instancia de las clases para crear las vistas

Respuesta larga

Ejecuta este comando para volcar el xml binario
aapt d xmltree apk_file_name res/layout/activity_main.xml ( aapt se puede encontrar en android-sdk-dir / build-tools / 23.0.2 / aapt.exe )

Esto mostrará los nodos xml (por ejemplo, LinearLayout , RelativeLayout , etc.) con sus atributos (por ejemplo, android:layout_width, android:layout_height ) y sus valores. Tenga en cuenta que las constantes match_parent (valor numérico 0xffffffff o -1 ) o wrap_content (valor numérico 0xfffffffe o -2 ) se pueden ver allí.

De hecho, puede usar este comando en cualquier otro archivo xml en la apk, por ejemplo, AndroidManifest.xml or layout files

El archivo apk es solo un archivo zip que contiene todos los archivos de clase java ( classes.dex ), todos los archivos de recursos compilados y un archivo llamado resources.arsc . Este archivo resource.arsc contiene toda la metainformación sobre los recursos y los nodos xml (por ejemplo, LinearLayout , RelativeLayout , etc.) y sus atributos (por ejemplo, android:layout_width ), incluidos sus ids . Estos ids referencia a los recursos reales en el archivo apk. Estos se resuelven a un valor en tiempo de ejecución. El proceso de resolución es inteligente en cuanto a cualquier redireccionamiento ( @dimen/... en lugar de 4dp o @color/... en lugar de "#FFaabbcc" ) y devuelve un valor.

Qué es un archivo XML compilado : Un archivo XML compilado es exactamente el mismo archivo XML con las referencias de recursos cambiadas a sus ids correspondientes. Por ejemplo, una referencia @string/ok será reemplazada por 0x7f000001 . Además, los atributos del espacio de nombres de android se cambian a sus valores enteros respectivos (por ejemplo, wrap_content se cambia a 0xfffffffe o -2 )

Cómo Android resuelve los recursos en tiempo de ejecución : el método inflater.inflate() analiza un archivo xml compilado y crea una jerarquía de vistas al crear una instancia de los nodos xml. Cada uno de los nodos xml está instanciado por una clase java (por ejemplo, LinearLayout.java, RelativeLayout.java). Para crear una instancia, el inflater analiza el archivo xml compilado, recopila todos los atributos de un nodo y creates una estructura empaquetada de tipo AttributeSet . Este AttributeSet se pasa al constructor de la clase. El constructor de la clase tiene la responsabilidad de recorrer el conjunto de AttributeSet y resolver cada uno de los valores de atributo.

Por ejemplo, para un diseño que contiene RelativeLayout , el inflater empaquetará layout_width y layout_height en un AttributeSet y lo pasará al constructor RelativeLayout (contexto de contexto, atributos AttributeSet, int defStyleAttr, int defStyleRes) . En este caso, algunos de los atributos y sus valores son resueltos por RelativeLayout.initFromAttributes() y el resto por el ViewGroup.initFromAttributes() primario.

android:id de una vista es solo otro atributo. El inflater almacena la identificación de cada vista llamando a setId(id) en esa vista después de la instanciación

Ahora para responder a su pregunta, R.id es una matriz java y my_textview es un número entero en esa matriz. El id de la vista my_textview es este entero (comienza con 0x7f). El método findViewById() realiza una búsqueda en profundidad en la jerarquía de esa vista para encontrar la vista correspondiente.

Espero que esto ayude. El link que proporcionó en su pregunta ya responde cómo los identificadores son generados por aapt.

Es un maravilloso sistema de administración de recursos para dispositivos con múltiples dimensiones de variaciones. Además, ¡la implementación es muy rápida! Con esto como base, permite implementar una funcionalidad de nivel superior (por ejemplo , Superposición de recursos en tiempo de ejecución )


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)

Este enlace podría ayudar a http://elinux.org/Android_aapt