Possible Duplicate:
Scope of R.id values
Could someone please clarify the scope of resource id's in Android? Recently I was making a custom title bar which contained a RelativeLayout called "header". I was invoking this title bar in the onCreate() handlers of each of my Activities thusly:
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.activity_layout);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title_bar);
One of my Activities had a TextView in its layout with the id of "header" and in that Activity's onCreate() I do a
TextView tv1 = (TextView)findViewById(R.id.header);
. . . which blew up at runtime with ClassCastException, apparently because it thought I was trying to cast a RelativeLayout to a TextView. Changing the name of the RelativeLayout in the title bar fixed it.
But I don't really understand this. Are Android resource id's global? If so why wouldn't this collision be caught at build-time?
Note that this question has been asked before on SO: Scope of R.id values . . . Where the OP said "as far as I can tell" R.id's are global but my question is not a duplicate because neither of my questions is really addressed in that one.
android:id. Resource ID. A unique resource name for the element, which you can use to obtain a reference to the View from your application.
You'll have to fully format your device data to change your Android phone's device ID. As the device ID is generated when you first set up the device, resetting the phone will change the Android device ID automatically.
Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view.
findViewById returns an instance of View , which is then cast to the target class. All good so far. To setup the view, findViewById constructs an AttributeSet from the parameters in the associated XML declaration which it passes to the constructor of View . We then cast the View instance to Button .
R.* values are global to their own type. So you can have a R.string
and an R.id
with the same name, but not two IDs with the same name. In your case, I feel that doing a build clean would have fixed your problem as well. For example, take a look at the R.java file contents:
public static final class drawable {
public static final int icon=0x7f020000;
public static final int info=0x7f020001;
public static final int menu=0x7f020002;
public static final int splash1=0x7f020003;
}
public static final class id {
public static final int ImageView02=0x7f070008;
public static final int bestTimeTextView=0x7f070005;
public static final int infoButton=0x7f070003;
public static final int infoImageView=0x7f070000;
public static final int levelSpinner=0x7f070002;
public static final int menuImageView=0x7f070001;
public static final int selectLevelTextView=0x7f070004;
public static final int startButton=0x7f070006;
public static final int timeTextView=0x7f070007;
}
public static final class layout {
public static final int info=0x7f030000;
public static final int menu=0x7f030001;
public static final int splash=0x7f030002;
}
public static final class raw {
public static final int down=0x7f040000;
public static final int up=0x7f040001;
}
public static final class string {
public static final int appname=0x7f060000;
public static final int besttime=0x7f060002;
public static final int help=0x7f060004;
public static final int selectlevel=0x7f060001;
public static final int start=0x7f060003;
}
Here I have the info name used in both drawable and layout parts, and the app functions perfectly. However, if I try adding two resources with the same ID, or two drawables with the same name, or two strings with the same name etc. it will not function properly.
Are Android resource id's global?
They are "global" within an activity. The title bar is in the activity. The layout is in the activity. Widgets from both will be in the activity. Widgets with the same ID from both will be in the activity and will represent a point of conflict for findViewById()
calls.
If so why wouldn't this collision be caught at build-time?
First, why would it? How is the build system supposed to know that you are are going to take res/layout/title_bar.xml
and res/layout/whatever_the_heck_you_called_it.xml
and use them both in the same activity?
Second, there is nothing wrong with having duplicate IDs. Your job, as a developer, is to call findViewById()
on whatever will give you a unique result. For example, you could have done:
TextView tv1 = (TextView)(findViewById(android.R.id.content).findViewById(R.id.header));
and kept the duplicate IDs. Going the route you did, of having distinct IDs, is a better choice here for maintainability. But there will be plenty of cases where you will intentionally have duplicate IDs, such as every AdapterView
you ever implement (e.g., ListView
), as their contents will tend to have duplicate IDs (e.g., each row in the ListView
is stamped out from the same row layout resource).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With