6

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.

4

3 回答 3

10

Android资源ID是全球性的吗?

它们在活动中是“全局的”。标题栏在活动中。布局在活动中。两者的小部件都将在活动中。两者中具有相同 ID 的小部件将在活动中,并代表findViewById()调用冲突点。

如果是这样,为什么不会在构建时捕获这种碰撞?

首先,为什么会这样?构建系统应该如何知道您将在同一个活动中使用res/layout/title_bar.xmlres/layout/whatever_the_heck_you_called_it.xml使用它们?

其次,拥有重复 ID 并没有错。作为开发人员,你的工作是调用findViewById()任何能给你带来独特结果的东西。例如,您可以这样做:

TextView tv1 = (TextView)(findViewById(android.R.id.content).findViewById(R.id.header));

并保留重复的 ID。走您所做的路线,拥有不同的 ID,对于可维护性来说是一个更好的选择。但是在很多情况下,您会故意使用重复的 ID,例如AdapterView您曾经实现过的每一个(例如,ListView),因为它们的内容往往具有重复的 ID(例如,ListView在资源)。

于 2012-08-16T14:02:10.027 回答
3

R.* 值对于它们自己的类型是全局的。所以你可以有一个R.string和一个R.id同名的ID,但不能有两个同名的ID。在您的情况下,我觉得进行构建清理也可以解决您的问题。例如,看一下 R.java 文件内容:

    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;
}

在这里,我在可绘制部分和布局部分中都使用了信息名称,并且应用程序运行良好。但是,如果我尝试添加两个具有相同 ID 的资源,或者两个具有相同名称的可绘制对象,或者两个具有相同名称的字符串等,它将无法正常工作。

于 2012-08-16T14:00:53.753 回答
0

R 只是一个充满静态整数的 java 类。您的应用程序中的 R.id.header 只能有一个值。在您的布局中使用相同的 id 是非常好的,但如果您在一个布局中使用相同的 id,您可能会遇到您遇到的确切问题。在您的情况下,findViewById 首先找到了您的 RelativeLayout 并返回它而不是 TextView。这只是搜索视图的顺序问题。例如,您仍然可以通过在 TextView 的直接父级上调用 findViewById 来绕过它。

于 2012-08-16T14:00:57.613 回答