J'essaie de comprendre ce que signifie "compiler des ressources".
J'ai lu de nombreux articles sur le sujet, mais je n'ai pas trouvé de réponse simple ... Le meilleur que j'ai lu était celui-ci: Comment le mappage entre les ressources Android et l'ID de ressources fonctionne-t-il? .
Si je comprends bien, lorsque nous compilons notre projet par ANT (Eclipse) ou par Gradle (AS), nous utilisons un outil appelé aapt - Android Asset Packaging Tool qui: Est utilisé pour générer des identifiants uniques. Pour chacune de nos ressources, telles que nos mises en page, nos styles, etc., stockez-les dans une table de correspondance. Ensuite, il conserve cette table de recherche en générant deux fichiers:
Donc, pour simplifier les choses: disons que cela se trouve dans activity_main.xml:
<TextView Android:id="@+id/my_textView"
Android:text="@string/hello_world"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content" />
Et je l’appelle depuis mon onCreate en utilisant:
findViewById(R.id.my_textView)
Dans mon fichier R.Java, je verrai:
public static final int my_textView=0x7f08003f;
Using: aapt dump resources sur l'apk généré, je vois qu'il contient deux lignes avec my_textView: Ressource ec 0x17f08003f com.example.lizi.liortest2: id/my_textView: flags = 0x00000000 .__ ressource 0x7f08003f com.example.lizi .liortest2: id/my_textView: t = 0x12 d = 0x00000000 (s = 0x0008 r = 0x00)
J'aurais pensé que ce fichier resources.arsc contiendrait non seulement l'ID de la ressource, mais également toutes les propriétés que j'ai définies pour la vue, telles qu'Android: layout_width = "wrap_content".
Alors maintenant, pendant l'exécution, lorsque VM tente d'exécuter findViewById(R.id.my_textView)
Comment sait-il quelle vue obtenir/ses propriétés à créer?
Je ne comprends tout simplement pas comment cela fonctionne ... Cette table de recherche ne devrait-elle pas contenir aussi les données de propriétés? Et quel est ce nombre 0x7f08003f? (Devrait-il représenter une valeur qui sera ensuite mappée à la mémoire physique dans laquelle l'objet sera stocké?)
TL; DR: avec l'aide du compilateur Android (aapt), les nœuds XML seront traduits en classes Java et les attributs correspondants en identificateurs numériques. Le moteur d'exécution Android utilise ces identifiants pour instancier des classes afin de créer les vues
Exécutez cette commande pour vider le fichier XML binaireaapt d xmltree apk_file_name res/layout/activity_main.xml
(aapt se trouve dans Android-sdk-dir/build-tools/23.0.2/aapt.exe)
Cela affichera les nœuds XML (par exemple, LinearLayout
, RelativeLayout
, etc.) avec leurs attributs (par exemple, Android:layout_width, Android:layout_height
) et leurs valeurs. Notez que vous pouvez y voir les constantes match_parent
(valeur numérique 0xffffffff
ou -1
) ou wrap_content
(valeur numérique 0xfffffffe
ou -2
).
En fait, vous pouvez utiliser cette commande sur tout autre fichier xml de l'apk, par exemple. AndroidManifest.xml or layout files
Le fichier apk est juste une archive Zip contenant tous les fichiers de classe Java (classes.dex
), tous les fichiers de ressources compilés et un fichier nommé resources.arsc
. Ce fichier resource.arsc
contient toutes les méta-informations sur les ressources, les nœuds xml (par exemple: LinearLayout
, RelativeLayout
, etc), leurs attributs (par exemple Android:layout_width
), la ressource id
'. Ces ressources id
'font référence aux ressources réelles du fichier apk. Les attributs sont résolus en une valeur au moment de l'exécution. Le processus de résolution est intelligent pour toute re-direction (@dimen/...
par opposition à 4dp
ou @color/...
par opposition à "#FFaabbcc"
) et renvoie une valeur utilisable (une valeur dimen
est résolue différemment d’une valeur color
.).
Ce qui est un fichier XML compilé: Un fichier XML compilé est exactement le même fichier XML avec les références de ressources modifiées en leur ids
correspondante. Par exemple, une référence @string/ok
sera remplacée par 0x7f000001
. De plus, les attributs de l'espace de noms Android
sont remplacés par leurs valeurs entières respectives (par exemple, wrap_content
est remplacé par 0xfffffffe
ou -2
).
Comment Android résout les ressources au moment de l'exécution: La méthode inflater.inflate()
analyse un fichier XML compilé et crée une hiérarchie de vues en instanciant les nœuds xml. Chacun des nœuds XML est instancié par une classe Java (par exemple, LinearLayout.Java, RelativeLayout.Java). Pour instancier, inflater analyse le fichier XML compilé, collecte tous les attributs d'un nœud et crée une structure compacte de type AttributeSet
. Cette AttributeSet
est transmise au constructeur de la classe. Le constructeur de classe a la responsabilité de parcourir la AttributeSet
et de résoudre chacune des valeurs d'attribut.
Par exemple, pour une présentation contenant RelativeLayout
, la inflater
encapsulera layout_width
et layout_height
dans un AttributeSet
et sera transmise au constructeur RelativeLayout (contexte de contexte, AttributeSet attrs, int defStyleAttr, int defStyleRes) . Dans ce cas, certains des attributs et leurs valeurs sont résolus par (RelativeLayout.initFromAttributes () _ et le reste par le parent ViewGroup.initFromAttributes () .
Android:id
d'une vue n'est qu'un autre attribut. L'inflater stocke l'identifiant de chaque vue par appelant setId(id)
sur cette vue après l'instanciation.
Maintenant, pour répondre à votre questionR.id
est un tableau Java et my_textview
est un entier de ce tableau. La id
de la vue my_textview
est cet entier (commençant par 0x7f). La méthode findViewById()
effectue une recherche en profondeur sur cette hiérarchie de vues pour trouver la vue correspondante.
J'espère que cela t'aides. Le lien que vous avez fourni dans votre question indique déjà comment les identifiants sont générés par aapt.
C'est un système merveilleux de gestion des ressources pour les appareils avec de multiples dimensions de variations. De plus, la mise en place est vraiment rapide !! Avec ceci comme base, cela permet d’implémenter des fonctionnalités de plus haut niveau (par exemple, recouvrement de ressources d’exécution ).
LayoutInflater gonfle la vue en utilisant des chaînes XML. Les chaînes XML compilées dans un fichier de ressources, comme vous l'avez mentionné dans votre question.
Veuillez vérifier ces extraits de code d’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
charge l'analyseur de ressources 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
utilise getResourceValue de AssetManager et appelle la méthode native loadResourceValue
. Cette méthode native appelle la méthode ResTable
's getResource pour obtenir les chaînes XML stockées dans un fichier de ressources.
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)
Ce lien pourrait aider http://elinux.org/Android_aapt