73 votes

Comment fonctionne le mappage entre les ressources Android et l'ID des ressources ?

Il est magique pour Android de localiser la ressource appropriée juste à travers le R.id.XXX .

A priori, les ressources sont compilées au format binaire, alors comment fonctionne cette logique de mappage sous le capot ?

Peut-être ça marche comme ça :

Par exemple, dans le layout1.xml on a :

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

et l'AAPT le générera dans le R.java :

public static final int button1=0x7f05000b;

Lorsque le *.apk est généré, le @+id/button1 doit être remplacé par "0x7f05000b".

Ainsi, quand nous appelons :

findViewById(R.id.button1);

nous continuons essentiellement à effectuer la recherche sur la base de l'ID, bien que l'ID soit un nombre comme 0x7f05000b.

Merci !

ADD

Ce que je veux vraiment savoir, c'est comment l'identifiant de la ressource est analysé dans le contenu de la ressource ? En d'autres termes, comment le runtime Android localise-t-il le contenu de la ressource avec l'id de la ressource comme seul indice ?

Par exemple, comment trouver une image dessinable avec un identifiant de ressource ? Ou comment trouver une valeur de chaîne de caractères avec un identifiant de ressource ?

184voto

hackbod Points 55292

Au moment de la construction, l'outil aapt rassemble toutes les ressources que vous avez définies (par des fichiers séparés ou des définitions explicites dans des fichiers) et leur attribue des ID de ressources.

Un ID de ressource est un nombre de 32 bits de la forme : PPTTNNNN. PP est le paquet pour lequel la ressource est destinée ; TT est le type de la ressource ; NNNNN est le nom de la ressource dans ce type. Pour les ressources des applications, PP est toujours 0x7f.

Les valeurs TT et NNNNN sont attribuées par aapt de manière arbitraire -- en fait, pour chaque nouveau type, le prochain numéro disponible est attribué et utilisé (en commençant par 1) ; de même, pour chaque nouveau nom dans un type, le prochain numéro disponible est attribué et utilisé (en commençant par 1).

Donc si nous avons ces fichiers de ressources gérés par aapt dans cet ordre :

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

Le premier type que nous voyons est "layout", ce qui donne TT == 1. Le premier nom sous ce type est "main", ce qui donne NNNN == 1. L'ID final de la ressource est 0x7f010001.

Ensuite, nous voyons "drawable", ce qui donne TT == 2. Le premier nom de ce type est "icon", qui reçoit donc NNNN == 1. L'ID final de la ressource est 0x7f020001.

Enfin, nous voyons un autre "layout" qui a TT == 1 comme avant. Il a un nouveau nom "listitem" et obtient donc la valeur suivante NNNN == 2. L'ID final de la ressource est 0x7f010002.

Notez que par défaut, aapt n'essaie pas de garder ces identifiants identiques entre les builds. Chaque fois que les ressources changent, elles peuvent toutes obtenir de nouveaux identifiants. Chaque fois qu'elles sont construites, un nouveau R.java est créé avec les identifiants actuels afin que votre code obtienne les valeurs correctes. Pour cette raison, vous ne devez jamais conserver les identifiants des ressources à un endroit où ils peuvent être utilisés dans différentes versions de votre application.

Une fois les ressources compilées et les identifiants attribués, aapt génère le fichier R.java pour votre code source et un fichier binaire appelé "resources.arsc" qui contient tous les noms, identifiants et valeurs des ressources (pour les ressources provenant d'un fichier distinct, leur valeur est le chemin d'accès à ce fichier dans le fichier .apk), dans un format qui peut facilement être mappé et analysé sur l'appareil au moment de l'exécution.

Vous pouvez obtenir un résumé du fichier resources.arsc dans un apk avec la commande "aapt dump resources <path-to-apk>".

Le format de la table des ressources binaires est documenté dans le fichier d'en-tête des structures de données des ressources ici :

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

L'implémentation complète de la lecture de la table des ressources sur le dispositif est ici :

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

7voto

Reno Points 22138

Si vous êtes intéressé par l'implémentation interne (côté périphérique), jetez un coup d'œil à loadDrawable() dans le document suivant Ressources.java . Reportez-vous à l'excellente réponse de hackbod pour obtenir des informations sur les points suivants l'extraction de données du table des ressources

Pour savoir comment les mises en page sont traduites en vues à partir d'identifiants de ressources, consultez le site suivant LayoutInfater .java

5voto

Dan Points 1835

D'après ce que je comprends, aapt génère automatiquement des identifiants uniques pour chacune de vos ressources et les stocke dans une table de consultation. Cette table de consultation est persistée dans le fichier "resources.arsc" situé dans "bin/resources.ap_" (c'est juste un fichier ZIP, donc n'hésitez pas à l'ouvrir en utilisant votre visualisateur ZIP préféré). La table de consultation est également conservée dans le fichier R.java, qui, comme vous le savez, vous permet de référencer vos ressources en Java.

Si vous voulez plus d'informations sur le fichier ARSC, je vous suggère de le googler ou d'examiner le code de l'article suivant http://code.google.com/p/Android-apktool/ .

-Dan

1voto

Edward Falk Points 3650

Une dernière remarque : pendant longtemps, je n'ai pas utilisé les mises en page relatives parce que de nombreux éléments doivent faire référence à des éléments situés plus bas dans le fichier xml, et je ne savais pas comment faire référence à un élément de type @id/foo qui n'avaient pas encore été définis.

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

Puis un jour j'ai réalisé (duh) que tu peux définir un id dans la référence ; il n'est pas nécessaire qu'il soit dans l'élément qui porte l'id :

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

0voto

ErikR Points 729

La magie réside dans le plug-in Eclipse et le fichier R.java qu'il génère automatiquement dans le dossier "gen" d'une application. Si vous jetez un coup d'oeil à ce fichier, vous verrez des mappages statiques pour chaque XXX dans R.xx.XXX où xx peut être anim, array, color, et tout autre type de ressource.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X