28

Ok so something that I am confused with is whether Android ids need to be unique or not. Here is why the confusion arises:
Let's just say there is an Activity that has an TextView (android:id="text") and a Button (android:id="button"). The Button sets the text of the text view to a random text. So, to add a listener, I will retrieve the button as
Button b = (Button) findViewById(R.id.button) and then add listener to do the task.
Now, I can refer to this same TextView from a DialogFragment, a Fragment and what not with the same id R.id.text and all the changes will ever be applied to this text view without doubt.

In case of subclassing BaseAdapter, you need to override the getView where you do the inflating if necessary and if not, you make changes. Now, you retrieve the Views in almost the same way. Almost.
You do a convertView.findViewById(..).

If all the views need to have a unique id, how does changing the content of View in the getView not result in haphazard behavior ?
I mean, all the views inflated have the same id as defined in layout.

My understanding is that the ids are unique in the context of the view that inflated them. Since I am a beginner, I am asking for clarification

Update after Ahmad's answer

So, what this means is I can not inflate two Fragment in an Activity by using the same layout. This will result in an exception. Both are inflated by the same Activity, hence belong to the same instance. The ids will conflict

An SO User
  • 24,612
  • 35
  • 133
  • 221
  • 1
    There won't be an exception thrown. It is much too expensive for Android to go through and check that there are not conflicting ids. The only issue is if you search for a view using `findViewById()`, you could receive back *any* of the views with that id. So just as long as the ids are unique in the subtree of the views you are searching, you will be fine. – Alex MDC Aug 05 '13 at 21:02
  • @AlexMDC Yes, exactly. You clarified it. I will get back any view if the ids are the same. :) – An SO User Aug 05 '13 at 21:03
  • "the ids are unique in the context of the view that inflated them". Do you mean, they should be unique in the context of the Activity or View whose `findViewById()` method is being called, if you want to avoid ID collisions? – LarsH Jun 02 '16 at 15:40

3 Answers3

34

In documentation You may read

An ID need not be unique throughout the entire tree, but it should be unique within the part of the tree you are searching (which may often be the entire tree, so it's best to be completely unique when possible).

It means there will be no exceptions if You use same id for all Your views but obviously layout will get useless then.

FindViewById works simply by traversing a tree until it finds first element with searched id and returns it (or null if doesn't find). If You had few elements with same id in tree You will always get same element, the one that is first in tree.

You may have plenty of fragments inflated with same layout just like you have ListView with each element having same layout, that is because inflater doesn't care about id values. It simply reads XML file and create a tree with correct view objects nothing more.

Gustek
  • 3,680
  • 2
  • 22
  • 36
2

You do a convertView.findViewById(..).

If all the views need to have a unique id, how does changing the content of View in the getView not result in haphazard behavior ?

This is because you create an instance of the view by inflating it. In this instance the ids need to be unique. Otherwise you will probably get a ClassCastException (If two different type of views share the same Id).

It would be impossible to maintain a ListView where every row would have to have unique identifiers for all its views.

So, what this means is I can not inflate two Fragment in an Activity by using the same layout. This will result in an exception. Both are inflated by the same Activity, hence belong to the same instance. The ids will conflic

No, fragments work in a different way. You have to return an inflated view in the fragments onCreateView() method. So each fragment has to inflate the view, which results in having 2 separate view objects.

Ahmad
  • 69,608
  • 17
  • 111
  • 137
2

Why you are using android:id="text"? You should use android:id="@+id/text" or android:id="@id/text" depending on what way you'll choose. Moreover, getView is relative to the item position on scrolled or not ListView

be4code
  • 688
  • 4
  • 15
  • Yes, my bad there. Sorry :) – An SO User Aug 05 '13 at 20:54
  • And yes, id is unique in specific area, ie. in `ListView` item when you are inflating a row id for `TextView` is different than id for `ImageView`. But for every row ids for `TextView` and `ImageView` are the same. – be4code Aug 05 '13 at 20:58
  • They are **different** views :) – An SO User Aug 05 '13 at 21:01
  • I've tried to show it as simply as I can ;) When you use `@+id/`, the ids are collected and depending on which item you are refering using simply R.id.text the system choose this one which you wanted – be4code Aug 05 '13 at 21:12
  • What is the significance of the `"@+id/"` in the ID? could you link to documentation? – dinosaur Apr 13 '16 at 09:59
  • I think here is good explanation [link](http://stackoverflow.com/questions/5025910/difference-between-id-and-id-in-android) – be4code Apr 13 '16 at 11:38