Как работает сопоставление между ресурсами android ресурсов и ID ресурсов?

Волшебным для Android является поиск подходящего ресурса только через R.id.XXX.

AFAIK, ресурсы компилируются в двоичный формат, так как эта логика отображения работает под капотом?

Может быть работает следующим образом:

Например, в layout1.xml мы получили:

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

и AAPT сгенерирует это в R.java:

public static final int button1=0x7f05000b;

Когда выделяется *. apk, @+ id/button1 с подстрокой "0x7f05000b".

Таким образом, когда мы вызываем:

findViewById(R.id.button1);

мы по существу по-прежнему выполняем поиск на основе идентификатора, хотя идентификатор - это число, такое как 0x7f05000b.

Спасибо!

ADD

То, что я действительно хочу знать, как синтаксис идентификатора ресурса анализируется в содержимом ресурса? Другими словами, как среда выполнения Android находит содержимое ресурса с идентификатором ресурса в качестве единственного ключа?

Например, как показано рисованное изображение с идентификатором ресурса? Или как показано строковое значение с идентификатором ресурса?

Ответ 1

Во время сборки инструмент aapt собирает все ресурсы, которые вы определили (хотя отдельные файлы или явные определения в файлах) и присваивает им идентификаторы ресурсов.

Идентификатор ресурса - это 32-битный номер формы: PPTTNNNN. PP - это пакет, для которого предназначен ресурс; TT - тип ресурса; NNNN - это имя ресурса в этом типе. Для ресурсов приложений PP всегда равен 0x7f.

Значения TT ​​и NNNN назначаются aapt произвольно - в основном для каждого нового типа присваивается и используется следующий доступный номер (начиная с 1); аналогично для каждого нового имени в типе, следующий доступный номер назначается и используется (начиная с 1).

Итак, если у нас есть эти файлы ресурсов, обработанные aapt в следующем порядке:

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

Первый тип, который мы видим, - это "макет", так что ему дается TT == 1. Первое имя под этим типом является "основным", поэтому ему предоставляется NNNN == 1. Конечный идентификатор ресурса - 0x7f010001.

Далее мы видим "drawable", так что задается TT == 2. Первое имя для этого типа - "значок", поэтому он получает NNNN == 1. Конечный идентификатор ресурса - 0x7f020001.

Наконец, мы видим еще один "макет", который имеет TT == 1, как и раньше. Это имеет новое имя "listitem", так что получает следующее значение NNNN == 2. Окончательный идентификатор ресурса - 0x7f010002.

Обратите внимание, что aapt по умолчанию не пытается сохранить эти идентификаторы одинаковыми между строками. Каждый раз, когда ресурсы меняются, они могут получить новые идентификаторы. Каждый раз, когда они создаются, создается новый R.java с текущими идентификаторами, поэтому ваш код получает правильные значения. Из-за этого вы никогда не должны сохранять идентификаторы ресурсов везде, где их можно использовать в разных сборках вашего приложения.

После компиляции ресурсов и назначений идентификаторов aapt генерирует файл R.java для вашего исходного кода и двоичный файл с именем "resources.arsc", который содержит все имена, идентификаторы и значения ресурсов (для ресурсов, которые приходят из отдельного файла, их значение - путь к этому файлу в .apk), в формате, который может быть легко воспроизведен и разобран на устройстве во время выполнения.

Вы можете получить сводку файла resources.arsc в apk с помощью команды "aap dump resources < path-to-apk > ".

Формат таблицы двоичных ресурсов задокументирован в файле заголовка для структур данных ресурсов здесь:

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

Полная реализация для чтения таблицы ресурсов на устройстве приведена здесь:

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

Ответ 2

Если вас интересует внутренняя реализация (сторона устройства), посмотрите на loadDrawable() в Resources.java. Обратитесь к высокому ответу hackbod за информацией о извлечении данных из таблицы ресурсов

Чтобы узнать, как макеты переведены в представление из идентификатора ресурса, выполните LayoutInfater.java

Ответ 3

Из того, что я понимаю, aapt автоматически генерирует уникальные идентификаторы для каждого из ваших ресурсов и сохраняет их в справочной таблице. Эта справочная таблица сохраняется как файл "resources.arsc", расположенный в "bin/resources.ap_" (это просто ZIP файл, поэтому не стесняйтесь открывать его с помощью любимого средства просмотра ZIP). Смотровая таблица также сохраняется как R.java, которая, как вы знаете, позволяет ссылаться на ваши ресурсы на Java.

Если вы хотите получить дополнительную информацию о файле ARSC, я бы предложил Googling или просмотрел код http://code.google.com/p/android-apktool/.

Дан

Ответ 4

Последнее замечание: в течение самого долгого времени я не использовал относительные макеты, потому что многие элементы должны ссылаться на элементы далее в XML файле, и я не знал, как ссылаться на @id/foo, который еще не определен.

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

Тогда однажды я понял (duh), что вы можете определить идентификатор в ссылке; он не должен находиться в элементе, который несет идентификатор:

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

Ответ 5

Магия находится в подключаемом модуле Eclipse и файле R.java, который автоматически генерируется в папке "gen" приложения. Если вы заглянете в этот файл, вы увидите статические сопоставления для каждого XXX в R.xx.XXX, где xx может быть анимированным, массивным, цветным и любым другим типом ресурса.