Are integer value of view IDs are always constant in android? - android

Are int value of R.id.view is always same?
I tried printed it in two devices and it was same.
I also changed name of id but still the value was same.
But will it stay the same in all scenarios?

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.

A View ID is generated during Compilation, so Yes the ID will be the same in each Device if the APK is the same. Pay attention that "different compilations could generate different IDs".

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"

Reference resource id from resource

I have a project with multiple flavors, apple and banana. It references a file that is stored in the raw resource directory. I would prefer to avoid naming each one database.sqlite and instead keep the name relevant to the flavor, apple.sqlite and banana.sqlite. In my code, I have a line that reads as
getResources().openRawResource(R.raw.apple);
Is it possible to create an integer resource that could essentially link to the right id, or would I be better off making a class in each flavor that would have the link to it?
You can create dedicated source sets for build types, product flavors (such as apple and banana), and build variants. You can create resource aliases, to give a resource another identifier. You should be able to mash these up to get what you want.
I assume, from your question, that you have apple/res/raw/apple.sqlite and banana/res/raw/banana.sqlite in your project. If so, then:
Create apple/res/values/ids.xml, and in there have <item type="raw" name="whatever">#raw/apple</item>
Create banana/res/values/ids.xml, and in there have <item type="raw" name="whatever">#raw/banana</item>
Use R.raw.whatever to identify this resource in your code in main
(where you can replace whatever with, like, whatever)
Here, you are setting up a common alias (whatever) for the resource, pointing the flavor-specific definition of the alias to the flavor-specific resource.

getResourceId method of TypedArray

I am reading docs about getResourceId() method. It says that:
Retrieves the resource identifier for the attribute at index. Note
that attribute resource as resolved when the overall TypedArray object
is retrieved. As a result, this function will return the resource
identifier of the final resource value that was found, not necessarily
the original resource that was specified by the attribute.
So
the first paragraph is clear:
Retrieves the resource identifier for the attribute at index.
the second is clear too:
Note that attribute resource as resolved when the overall TypedArray
object is retrieved.
but what means the 3 paragraph? why it could return not necessarily the original resource id?
As a result, this function will return the resource identifier of the
final resource value that was found, not necessarily the original
resource that was specified by the attribute.
From the
documentation:
TypedArray obtainStyledAttributes (AttributeSet set,
int[] attrs,
int defStyleAttr,
int defStyleRes)
....
When determining the final value of a particular attribute, there are
four inputs that come into play:
Any attribute values in the given AttributeSet.
The style resource specified in the AttributeSet (named "style").
The default style specified by defStyleAttr and defStyleRes
The base values in this theme.
This is because Resource Merging needs to happen before the TypedArray is retrieved.
The Gradle-base build system uses a new merging mechanism for
resources. In previous build system, merging was done by passing a
list of resource folders to aapt which acted as overlays, alongside
the --auto-add-overlay to ensure that new resources in the overlays
would be automatically added (default behavior is for overlays is to
only override existing resources, not create new ones).
One of the goals of the Gradle-based build system was providing more
flexibility, and one frequently asked feature request was the ability
to have more than one resources folders. aapt is not able to handle
this so the new build system introduces a new merging mechanism that
is run ahead of aapt and generates a single, merged, resources folder
that is fed to aapt. This merging has the advantage of being
incremental, both through Gradle's input/output change detection, and
in the way it is implemented (ie it can rerun the merge by only
applying the change in a single file).
The merged resources are coming from 3 types of sources:
The main resources, associated with the main sourceSet, generally located in src/main/res
The variant overlays, coming from the Build Type, and Flavor(s).
The Library Project dependencies, which contribute resources through the res entry in their aar bundle.
E.g. If you use different productFlavors or buildTypes you may have different resources for each flavor. So the one originally set at the time of development may be different from what is actually presented after changing the flavor.

Resource scope for #+id/ declarations?

When working through the tutorial to build my first Android application I reached a section where it states the #+id/ prefix not only references a resource that is defined in the gen/R.java file, but that the + sign also indicates its first encounter with it so it will create it. Consider this code snippet:
<EditText android:id="#+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/edit_message" />
After reading through the side-bar in the first link, related to resources, and the article it linked to named Providing Resources (at a somewhat cursory level), I'm unable to get a very clear statement from the documentation on the scope of the resource with the #+id/ prefix. I understand that you can have a resource with the same name scoped inside each prefix:
Note: This string resource has the same name as the element ID: edit_message. However, references to resources are always scoped by the resource type (such as id or string), so using the same name does not cause collisions.
but what I'm driving at is this. Based on the documentation it appears that I can't have two controls resourced as edit_message in two different activities because there would be a conflict.
My concern here is that I'd presumably have to prefix my id attributes with the Activity name to keep them unique so I can access these controls from code.
Am I correct in my statement and assumptions here?
You can place that exact block of XML in another layout file and it will work just fine. #+id generates a new id if it is not defined yet. When your app gets packaged, the packaging tool will create the id once and all the others will correctly refer to that id.
As long as you don't end up with two UI components in the same layout with the same id, everything's ok.

Different res/raw file have the very same ID?

I understand all resources within any given namespace (ie com.test.android vs. com.test2.android) will have unique resource id assigned. Now if I call com.test.android within com.test2.android, I find out two different resources got assigned the same resource id thus my getResources().openRawResrouce() is getting the wrong file.
So I have a jar file compiled including res/raw/test.zip as my SDK. Then I included this sdk.jar in a separate project and tried to access this res/raw/test.zip via
getInstance().getContext().getResources().openRawResource(com.mycompany.android.R.raw.test)
Yet it returns the wrong file which is com.mycompany.res/drawble-hdpi/lc_launcher.png. I then discovered that's because com.mycompany.android.R.raw.test(res/raw file in my SDK) has the very same ID as com.example.resourcetest.R.raw.ic_launcher
What'd be the appropriate fix?
Thanks,
Lee

Categories

Resources