How does the mapping between android resources and resources ID work?
At build time, the aapt tool collects all of the resources you have defined (though separate files or explicit definitions in files) and assigns resource IDs to them.
A resource ID is a 32 bit number of the form: PPTTNNNN. PP is the package the resource is for; TT is the type of the resource; NNNN is the name of the resource in that type. For applications resources, PP is always 0x7f.
The TT and NNNN values are assigned by aapt arbitrarily -- basically for each new type the next available number is assigned and used (starting with 1); likewise for each new name in a type, the next available number is assigned and used (starting with 1).
So if we have these resource files handled by aapt in this order:
layout/main.xml
drawable/icon.xml
layout/listitem.xml
The first type we see is "layout" so that is given TT == 1. The first name under that type is "main" so that is given NNNN == 1. The final resource ID is 0x7f010001.
Next we see "drawable" so that is given TT == 2. The first name for that type is "icon" so that gets NNNN == 1. The final resource ID is 0x7f020001.
Last we see another "layout" which has TT == 1 as before. This has a new name "listitem" so that gets the next value NNNN == 2. The final resource ID is 0x7f010002.
Note that aapt by default makes no attempt to keep these identifiers the same between builds. Each time the resources change, they can all get new identifiers. Each time they are built, a new R.java is created with the current identifiers so your code gets the correct values. Because of this, you must never persist resource identifiers anywhere where they can be used across different builds of your app.
Once the resources are compiled and identifiers assigned, aapt generates the R.java file for your source code and a binary file called "resources.arsc" that contains all of the resource names, identifiers, and values (for resources that come from separate file, their value is the path to that file in the .apk), in a format that can easily mmapped and parsed on the device at runtime.
You can get a summary of the resources.arsc file in an apk with the command "aapt dump resources <path-to-apk>".
The format of the binary resource table is documented in the header file for the resource data structures here:
https://github.com/android/platform_frameworks_base/blob/master/libs/androidfw/include/androidfw/ResourceTypes.h
The full implementation for reading the resource table on the device is here:
https://github.com/android/platform_frameworks_base/blob/master/libs/androidfw/ResourceTypes.cpp
resource ID R.id.map is added automatically to the Android project when you build the layout file
You are not dynamically inserting the framgent, instead you are finding the map fragment using findFragmentById. This means that you need to have the map fragment in your layout file.
You are probably missing the following in your layout file
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Are integer value of view IDs are always constant in android?
For any particular app resource, the particular R class associated resource ID will be the same in all scenarios during runtime as this resource ID is generated by aapt during compile time.
From Android Documentation:
Once you provide a resource in your application, you can apply it by referencing its resource ID. All resource IDs are defined in your project's R class, which the aapt tool automatically generates. When your application is compiled, aapt generates the R class, which contains resource IDs for all the resources in your res/ directory.
Thus printing it in two devices will result the same int value, provided that the same apk is used. Also note that the resource id is final
in the respective R subclass.
From this answer:
Note that aapt by default makes no attempt to keep these identifiers
the same between builds. Each time the resources change, they can all
get new identifiers. Each time they are built, a new R.java is created
with the current identifiers so your code gets the correct values.
Because of this, you must never persist resource identifiers anywhere
where they can be used across different builds of your app.
Any changes to the resource might make the resource get an new R class resource ID.
Based on the way in which the R class Resource ID are calculated, as described in that answer, I think since you only changed the name of the XML resource ID, and didn't change the type of the resource nor the placement of the respective View object declaration in the respective XML file, the same R class Resource ID is being calculated.
What is the use of the res/values/public.xml file on Android?
The file res/values/public.xml is used to assign fixed resource IDs to Android resources.
Consider these set of string resources in res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="string1">String 1</string>
<string name="string3">String 3</string>
</resources>
The Android Asset Packaging Tool (aapt) might assign the following resource IDs for these resources when the app is compiled:
public final class R {
// ...
public static final class string {
public static final int string1=0x7f040000;
public static final int string3=0x7f040001;
}
}
Now, change the set of string resources to
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="string1">String 1</string>
<string name="string2">String 2</string>
<string name="string3">String 3</string>
</resources>
and you'll notice that the resource ID for @string/string3
has changed:
public final class R {
// ...
public static final class string {
public static final int string1=0x7f040000;
public static final int string2=0x7f040001;
public static final int string3=0x7f040002; // New ID! Was 0x7f040001
}
}
To prevent this, you can use res/values/public.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<public type="string" name="string3" id="0x7f040001" />
</resources>
which will result in the resource IDs being assigned as follows:
public final class R {
// ...
public static final class string {
public static final int string1=0x7f040000;
public static final int string2=0x7f040002;
public static final int string3=0x7f040001; // Resource ID from public.xml
}
}
Applications rarely have any use for res/values/public.xml since the resource IDs assigned to resources does not matter. When they change, the entire application is rebuilt anyway so any references in Java code to resources by resource ID will be updated.
The most significant user of res/values/public.xml is the Android platform itself. Applications built against old versions of Android assumes that certain resource have a certain resource ID. For example, the Android resource @android:style/Theme
must always have the resource ID 0x01030005 for the platform to be backwards compatible with apps built against old versions of the platform.
If you are curious about more details on how resource IDs are assigned, please refer to this answer: How does the mapping between android resources and resources ID work?
Android compiled resources - resources.arsc
TL;DR: With the help of android asset packagin tool(aapt), xml nodes get translated to Java classes and the corresponding xml attributes get translated to numerical Ids. Android run-time works with these numeric ids to instantiate classes and create the views
TL;R
Run this command to dump the binary xmlaapt d xmltree apk_file_name res/layout/activity_main.xml
(aapt can be found in android-sdk-dir/build-tools/23.0.2/aapt.exe)
This will show the xml nodes (e.g. LinearLayout
, RelativeLayout
, etc) with their attributes(e.g. android:layout_width, android:layout_height
) and their values. Note that, the constants match_parent
(numeric value 0xffffffff
or -1
) or wrap_content
(numeric value 0xfffffffe
or -2
) can be seen there.
As a matter of fact, you can use this command on any other xml files in the apk e.g. AndroidManifest.xml or other layout files
The apk file is just a zip archive containing all the java class files(classes.dex
), all the compiled resource files and a file named resources.arsc
.
This resource.arsc
file contains all the meta-information about the resources. Some of those are...
- the xml nodes(e.g.
LinearLayout
,RelativeLayout
, etc), - the attributes(e.g.
android:layout_width
), - the resource
id
's.
The resource id
's refer to the real resources in the apk-file. The attributes are resolved to a value at runtime. The resolution process is smart about any re-direction (@dimen/...
as opposed to 4dp
or @color/...
as opposed to "#FFaabbcc"
) and returns a usable value(a dimen
value is resolved differently than a color
value).
Whats a compiled XML file:
A compiled XML file is just the same XML file with the resource references changed to their corresponding ids
. For example, a reference @string/ok
will be replaced by 0x7f000001
. Moreover, the attributes from android
namespace is changed to their respective integer values(e.g. wrap_content
is changed to 0xfffffffe
or -2
)
How Android resolves resources at runtime:
The methodinflater.inflate()
parses a compiled xml file and creates a view hierarchy by instantiating the xml nodes. Each of the xml nodes is instantiated by a java class(e.g. LinearLayout.java, RelativeLayout.java). To instantiate, the inflater parses the compiled xml file, collects all the attributes of a node and creates a packed structure of type AttributeSet
. This AttributeSet
is passed to the class constructor. The class constructor has the responsibility of walking the AttributeSet
and resolving each of the attribute values.
For example, for a layout containing RelativeLayout
, the inflater
will pack layout_width
and layout_height
into a AttributeSet
and pass it to the constructor
RelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes).
In this case, some of the attributes are resolved by RelativeLayout.initFromAttributes(). The rest of the attributes are resolved by the parent ViewGroup.initFromAttributes(). The attribute android:id
of a view is just another attribute. After inflating, the inflater stores the id of each view by calling setId(id)
on that view after instantiation
Now to answer your questionR.id
is a java array and R.id.my_textview
is an integer in that array. The id
of the view my_textview
is this integer(starts with 0x7f). The method findViewById()
does a depth-first search on that view hierarchy to find the respective view.
Hope this helps. The link you provided in your question already answers how the ids are generated by aapt.
Its a wonderful system of managing resources for devices with multiple dimensions of variations. Moreover, the implementation is really fast !! With this as the foundation, it allows to implement higher level functionality(e.g. Runtime Resource Overlay)
What limits are there on the number of Android resources?
After a lot of experimenting, it seems that you can have up to 16 bits worth of resources (65,536 resources) for each resource type. (There may be additional bits reserved for future use, which would reduce the max resource count, but I couldn't find any evidence of this.) It would be nice if someone could provide an authoritative answer, but after a year, I'm giving up.
EDIT (see the comment below by @B T): Based on this answer by hackbod in another thread, It seems that there are, indeed, 16 bits available, so one can have up to 65,535 resources of any one type (not 65,536, because zero is not available). Also, note that this limit applies only to the number of resources for a single configuration (locale, pixel density, etc.). Variations of a resource for different configurations share the same resource ID and don't contribute to the count. So you can actually have a lot more than 65,535 resources of any one type (e.g., layout or string), just not for any one configuration.
Are resources final in Android?
The ids are converted to a unique integer value and by switching on the value of R.id.myvalue
that int value will always map to that resource.
The linked question is from 2011.
As for if
or switch
, if you have only a couple of values then an if statement might be better, a longer list then a switch, which is programming basics. Please note this is not set in stone. When to use If-else if-else over switch statments and vice versa
Related Topics
Recyclerview - How to Smooth Scroll to Top of Item on a Certain Position
Use a Custom Contextual Action Bar for Webview Text Selection
Fusedlocationapi.Getlastlocation Always Null
Alert Dialog from Android Service
Add New Item Count to Icon on Button - Android
Monodroid: Error When Calling Constructor of Custom View - Twodscrollview
How to Securely Store Credentials (Password) in Android Application
Installation Error: Install_Parse_Failed_Manifest_Malformed
Blurry Svg Images in Chrome for Android
How to Use Single Textwatcher for Multiple Edittexts
Can an Android App Connect Directly to an Online MySQL Database
Using Viewpagerindicator Library with Android Studio and Gradle
Edittext: Disable Paste/Replace Menu Pop-Up on Text Selection Handler Click Event
Get Center Visible Item of Recycleview When Scrolling