Why is it necessary to use #+id instead of #id? - android

I know the difference between #+id and #id (see this accepted answer). However, I always get the feeling that I'm doing the job of the AAPT compiler when I write the '+' in #+id.
Is there a reason the resource compiler cannot infer by itself if an identifier must be created or just reused? An underlying hashtable structure would do the job: every resource with the same id go into the same bucket, and if the key does not exist, just create it.

Probably the compiler would not be able to differentiate between a 'right' and a 'wrong' id. If it finds a new id (i.e. one that is not in the underlying hashtable), it would always assume it to be a right, new id. It would not be able to differentiate between an actual new id and a mistyped id.

I could imagine it is to help the programmer.
If you did not need the #+id construction then all #id references/constructions would be valid, then it would be difficult to track down an error, as the compiler would not fail on incorrect references (as it would simply construct the typo id).
Put differently, all id reference errors would have to be discovered at runtime.
Edit:
Just noticed the similar answer by Piovezan, regarding your comment:
Maybe, but the result is that many devs use #+id everywhere, since there is no error if the id is already defined, and everything works just fine. That means the compiler tests if the id already exist, but not if it does not exist, that's crazy
Then those developers are misusing the #+id construction imo.
It is still much better to have the option to distinguish between #+id and #id, since (for those who does not misuse the #+id) the compiler has a chance of giving a compile time error on wrong references.
Edit2
And to address the comment:
That's the link I gave in the first sentence. It explains the difference but does not answer why the '+' cannot be automatically infered by AAPT
I believe it can, it just does not due to the argumentation above (i believe).

with #+id you are adding id to R.java which allows you to reference it from Java classes while with #id you are not. You can use #id only if specific id is already created and you are referencing it in another view e.g. android:layout_below="#id/some_id"

Related

Why does the designer use "#+id" instead of "#id" for constraints?

I've always understood #+id to indicate the creation of a new ID (generally used with android:id), and #id to reference it elsewhere, as explained at length in a popular question here and in the official documentation:
The at-symbol (#) at the beginning of the string indicates that the XML parser should parse and expand the rest of the ID string and identify it as an ID resource. The plus-symbol (+) means that this is a new resource name that must be created and added to our resources (in the R.java file). There are a number of other ID resources that are offered by the Android framework. When referencing an Android resource ID, you do not need the plus-symbol, but must add the android package namespace...
That this is not enforced is a bit odd; you can just use #+id everywhere, multiple times with the same id, and it does not seem to be an error or problem (unless you use the same id with multiple android:id declarations).
When using the graphical designer in Android Studio with constraint layout (it could in fact be with everything, I have not checked), whenever a constraint is added it will declare them like this:
app:layout_constraintTop_toBottomOf="#+id/rlistfrag"
Where rlistfrag is assigned to another element with android:id in the same file -- if it didn't exist already, the designed could not have created the constraint, so there can be no contextual ambiguity.1 According to the docs this amounts to twice declaring "a new resource name that must be created and added to our resources".
It seems the semantics here are not, by omission at least, exactly as described in the docs. Why does the designer do this and what are those omitted semantics?
Or could there? What all this implies to me is that elements may be processed in any order so the point is whenever an id is first encountered it will be created, even if it is not associated with an existing element.
There's a bit in the doc guide on layout resources that confirms the id will only be set the first time:
The plus symbol, +, indicates that this is a new resource ID and the aapt tool will create a new resource integer in the R.java class, if it doesn't already exist.
Which need not mean the elements aren't processed in order.
It is applied in all layout components. whenever you want to mention "id" you have to use "#+id"

Why does the R class not contain the field type?

Whenever we want to inflate a view or get a resource we have to cast it in run-time. views, for example, are used like so:
In the past, we would have needed to cast it locally
(RelativeLayout) findViewById(R.id.my_relative_layout_view)
Now, we use generics
findViewById<RelativeLayout>(R.id.my_relative_layout_view)
my question is why doesn't the compiler(or whoever generates the R class) doesn't also keep some kind of a reference to the type of the element(doesn't matter if it's a string or an int or any other type) that way casting problems should not occur
We cannot really speculate on that, that would be a design choice.
It might be that they wanted to avoid bloating the APK. Every ID would need a full package name to the class. So would each ID in android.R too. Since R is packaged in every APK.
Solutions
However, if you are using Kotlin, you can even do away with the generics check. Kotlin will determine it automatically.
val view = findViewById(R.id.my_relative_layout_view)
view.method()
Or event simpler, if you use synthetics:
my_relative_layout_view.method()
Also, if you are using data bindings, you can just access it like this:
binding.my_relative_layout_view.method()

Android: "#+id/" and "#+id/"

According to this thread I need to use #+id/ for the first time to make resource be created.
But what if I forget that this resource was previously created and create it again with #+id/? I have some input and set nextFocusDown for the element that is still not declared.
<EditText
...
android:nextFocusDown="#+id/myinput2"/>
200 lines below I create this element with #+id because I forgot that it's already declared.
<EditText
...
android:id="#+id/myinput2"/>
It works like this but can it cause an issue?
Some quick definitions:
#+id/foo means "use the id foo, and create it if it doesn't exist"
#id/foo means "use the id foo" (which will be an error if the id foo doesn't exist)
Previously, there were reasons to prefer #id over #+id (the system could tell you if you tried to reference a view via an id that didn't exist), but now the system is smart enough that even writing android:layout_below="#+id/idthatdoesntexistanywhere" will be tagged as an error:
So just always use #+id.
It works like this but can it cause an issue?
No, it can't. Always use #+id/. By now, the Android build environment is smart enought to figure it out.
If you put two elements with the same id in the same layout file, it generates an IDE error (red underline) and you won't be able to compile.

Android xml id naming

There are some questions about naming id in xml layout.
If i have a Activity used to create student.
What is the most suitable id for the EditText of student name?
et_student_name
et_name
et_create_student_name
I always use 3, because it is relate to the class name.But sometimes i think it is too long. I want to use 2 / 3, it is shorter but i am afraid it will repeated with other xml.
What is the good naming for the id?
Is it not good on repeated id in different xml layout?
Waiting for Help,
Thank you.
First, unless you are creating a distributed "jar" or "SDK" then you will discover name conflicts at build time. Worry about it then, not now. You are spending more time trying to avoid the problem than it's worth. Sometimes you need to prevent problems, but this isn't one of them.
If you are still worried, then there are 2 prefixes you can consider using. First, add a prefix that is somewhat descriptive of the XML file that has the element. For example, if the XML file is called "create_student.xml" then add "cs_" as the element for the prefix. (FYI - This really sucks when you change the filename, but that rarely happens.)
Second, add a prefix (or another prefix) for the package/class you are targeting. This prevents duplicates for SDK's and other libraries that may end in another developer's build. For example, if your SDK is "Student Registration and Identification" then add "sri_" to each element in the package.
The rest of the name is solely up to you. Having "et_" in the name for an EditText is helpful, the rest is going to be either "too long" or "not enough" almost every time.
to add to #AjayP.Prajapati your ids should not be the same as java keywords like break,continue ,switch,for etc..., and also your ids do not need to be special. if you have repeated ids the first occurrence will be returned.

what does the "#+android:id/title" mean?

In normal, we should use #+id/ to define an id and use #id to reference an id. Today I found #+android:id/title in apps/settings/res/layout/preferenc_progress.xml.
How to understand it and how to use it?
It is used for resources that are shipped with the SDK.
You can take a look at them by browsing to
[PATH TO ANDROID SDK]/platforms/android-[VERSION]/data/res
By using the android in android.R.whatever you just specify the R file to look up. For more information you should read Accessing Platform Resources.
That belongs to the app preferences activity screen definition.
title and summary are standard Android fields of a TextView preference item.
I think it does the same thing. It's just a more formal way of saying it by specifying where the namespace is.
I've never met this way of giving id, but in theory this means adding new id title to android package. So you'll be able to use it in your code like android.R.id.title. But I'm not sure resource compiler will really create any id in android package. I think it can be used only with predefined ids. But I'll give you more precise answer later, when I'll be able to check it.
EDIT: I've checked it and found some differences. Firstly, if you define Android's id using #+android:id/some_id, which is already present in SDK, this id will not be defined in your R.java file. If it's not present in SDK, it will be defined in R.java, but with different kind of value. Secondly, if you'll try to convert id from its string representation to int value, Resources.getIdentifier() method will return 0 in case of #+android:id format.
This means it will create an id in your resource file.

Categories

Resources