web-dev-qa-db-fra.com

Comment fonctionne le mappage entre Android ressources et ID de ressources?

Il est magique pour Android de localiser la bonne ressource juste à travers R.id.XXX .

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

Peut-être cela fonctionne comme ceci:

Par exemple, dans le layout1.xml, nous avons:

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

et AAPT générera ceci dans le R.Java:

public static final int button1=0x7f05000b;

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

Ainsi, lorsque nous appelons:

findViewById(R.id.button1);

nous faisons essentiellement toujours la recherche basée sur l'ID, bien que l'ID soit un nombre comme 0x7f05000b.

Merci!

AJOUTER

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

Par exemple, comment trouve-t-on une image dessinable avec un identifiant de ressource? Ou comment une valeur de chaîne est-elle trouvée avec un ID de ressource?

69
smwikipedia

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

Un ID de ressource est un nombre 32 bits de la forme: PPTTNNNN. PP est le package auquel la ressource est destinée; TT est le type de la ressource; NNNN est le nom de la ressource dans ce type. Pour les ressources d'applications, PP est toujours 0x7f.

Les valeurs TT et NNNN sont attribuées arbitrairement par aapt - fondamentalement pour chaque nouveau type, le numéro disponible suivant est attribué et utilisé (en commençant par 1); de même pour chaque nouveau nom dans un type, le le numéro disponible suivant 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 "mise en page" de sorte que soit donné TT == 1. Le premier nom sous ce type est "principal" de sorte que soit donné NNNN == 1. L'ID de ressource final est 0x7f010001.

Ensuite, nous voyons "drawable" de sorte que soit donné TT == 2. Le premier nom pour ce type est "icon" pour que NNNN == 1. L'ID de ressource final soit 0x7f020001.

Enfin, nous voyons une autre "mise en page" qui a TT == 1 comme avant. Elle a un nouveau nom "listitem" afin d'obtenir la prochaine valeur NNNN == 2. L'ID de ressource final est 0x7f010002 .

Notez que aapt par défaut n'essaye 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'ils sont construits, 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 identificateurs de ressources où qu'ils puissent ê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, identificateurs et valeurs des ressources (pour les ressources qui proviennent d'un fichier séparé , leur valeur est le chemin d'accès à ce fichier dans le .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 de ressources binaires est documenté dans le fichier d'en-tête des structures de données de ressources ici:

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

L'implémentation complète pour lire le tableau des ressources sur l'appareil est ici:

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

177
hackbod

Si vous êtes intéressé par l'implémentation interne (côté appareil), jetez un œil à loadDrawable () dans Resources.Java . Reportez-vous à l'excellente réponse de hackbod pour plus d'informations sur extraire des données detable de ressources

Pour savoir comment les dispositions sont traduites en vues à partir de l'ID de ressource, consultez LayoutInfater . Java

7
Reno

D'après ce que je comprends, aapt générera automatiquement des ID uniques pour chacune de vos ressources et les stockera dans une table de recherche. Cette table de correspondance est conservée en tant que fichier "resources.arsc" situé dans "bin/resources.ap_" (ce n'est qu'un fichier Zip, alors n'hésitez pas à l'ouvrir en utilisant votre visionneuse Zip préférée). La table de recherche est également conservée en tant que R.Java, ce qui, comme vous le savez, vous permet de référencer vos ressources en Java.

Si vous souhaitez plus d'informations sur le fichier ARSC, je vous suggère de le rechercher sur Google ou de consulter le code de http://code.google.com/p/Android-apktool/ .

-Dan

5
Dan

Une dernière remarque: pendant la plus longue période, je n'ai pas utilisé de dispositions relatives car de nombreux éléments doivent faire référence à des éléments plus bas dans le fichier xml, et je ne savais pas comment référencer un @ id/foo = qui n'avait pas encore été défini.

<!-- 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 vous pouvez définir un id dans la référence; il ne doit pas nécessairement être dans l'élément qui porte l'identifiant:

<!-- works -->
<TextView Android:layout_above="@+id/foo">above</textview>
<TextView Android:id="@id/foo">below</textview>
1
Edward Falk

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 regardez 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.

0
ErikR