int foo = 0xff;
String label = getNameOfFoo(foo);
System.out.println(label);// this should print "foo";
private String getNameOfFoo(int n){
String ret;
///WHAT COULD I DO HERE TO MAKE THIS A REALITY?
return ret;
}
Before you jump on me with "Why in GOD'S name would you need this?!" I will say that my goal is get around Android's mechanism of identifying my View id's as strings (ie. "id=#+id/user_name") but having to get it back in my code as int user_name = R.id.user_name. This works fine when I know that there is a "user_name" label. But goes to crap when I don't. I'm trying to write a skinnable app that may or may not contain all sorts of things in the xml, and I need a way to inspect the ids as strings.
What you described can't be done in Java. Could you explain your real problem a bit more? I have made a skinnable Android application.
Edit: Does it help you if you can go from name to id instead? You can in that case look at this thread:
How do I get the resource id of an image if I know its name?
I did however not solve it that way, and don't see a need for it.
You can use Context.getResources() for this.
int resID = getResources().getIdentifier("label_name", "drawable", "com.test.app");
And the returned resID. If it's 0 then the label is not found. Read here for more about Resources.
I have an app which is somewhat skinnable; the user can select one of a set of drawable resources to use as a background and I did not wish to hard-code the drawable set. What I did is name the id of each drawable using an identifiable pattern, something like "background_X", where "background_" was fixed and X could be completely free-form.
I then used reflection on the R class to determine at runtime, each of the candidate backgrounds, and presented them to the user by resource ID. When the user made their selection, I stored the reflected name in sharedPrefs rather than the resource ID... this allowed updates (which could potentially re-number each ID) to retain the user's settings.
Reflection can also be used to convert the number (foo) into a name but you need to walk through everything in R.[attr|drawable|id|etc.].* to find the match, and if you add resources to the category you will run the risk of values changing.
Related
I have heard that using editor.putString("Message","Hello"); is bad practice, and you should instead do editor.putString(getString(R.string.messagestring),"Hello");. But why? It is longer and has the same result, and looks more messy imo. Is it because it's harder to make a typo?
Here is an example from Signal:
Source
if (params[0] < SCREENSHOTS) {
boolean screenSecurity = PreferenceManager.getDefaultSharedPreferences(context).getBoolean(TextSecurePreferences.SCREEN_SECURITY_PREF, true);
TextSecurePreferences.setScreenSecurityEnabled(getApplicationContext(), screenSecurity);
}
String values in code for human readable text are bad.
Doing so makes localization impossible.
Values from R.string. on the other hand automagically use the right language (given that you use values, values-es, values-fr, ... and put translations)
Note: You should probably not translate the key of a SharedPreference but the value ("Hello") part since that's presumably the human readable thing.
editor.putString("message", getString(R.string.messagestring));
The key could change if the user changes device language which means the old stored value will no longer be found under the new key. If you want keys in a central place it's a good idea to have them defined as static final constants in code.
editor.putString(MyPrefConstants.PREF_MESSAGE, getString(R.string.messagestring));
I would actually consider using keys that come from R.string a very questionable design decision. This applies to anything that is intended to be machine-consumed rather than visible text to the user. There are a few exceptions but they are rare.
It's Not Necessary but Good Practice.
eg.
editor.putString("Message","Hello");
here the key -> "Message"
it is possible that sometimes you make a TYPING ERROR or SPELLING MISTAKE of writing "Message" to "Massage" or something else.
to avoid these type of situations, we should write in this way
editor.putString(getString(R.string.messagestring),"Hello");
It's all about maintenance, reusability, cleanness and if needed easier localization. Take for example "Message".
How many times would you use this string in your code if it is the key for Preferences? More than 1, right? Imagine that you write over and over "Message". Isn't it possible to misspell it at least once? Well you can't misspell a string resource, because the compiler won't let you.
Another thing: you know where all your UI strings are so you know where to look when you need to change 1 of them and once you do it is changed throughout the app.
Finally if you want your up to be multilingual this is the only way with the Editor provided by AS.
Edit: As for the question if strings like keys for Preferences should be in the Resources my answer is yes. It's up to the programmer to give proper ids to the string resources so to distinguish the UI items from the in-app items.
I'm trying to do a simple text game where the player has a weapon.
I want that, when clicking a certain option, the value that holds the weapon name "knife" gets updated to "sword".
I made a resources string that holds the "knife" value but can't seem to find a syntax that will update it.i already read that maybe you can't change resource values. Is this true?
If it is. How do I solve this?
Thanks.
It seems like you really need to go back and start with the basics of Android and Internationalization. It is not possible to update a resource at runtime, as you have correctly discovered, so it is your approach that needs to change.
Here is an example:
TextView text;
String value = getString(R.string.knife);
text.setText(value);
It seems that onClick you try to do something like:
setString(R.string.knife, "sword");
Which is impossible. Instead, you need to have the two strings as separate resources and then switch your value to the new resource when needed. So simply:
value = getString(R.string.sword);
text.setText(value); //and reset the display
For reference, if anyone stumbles upon the same problems, I found a good solution with Shared Preferences. It allows saving variable values in the device's memory.
Lets say we have something like this in strings.xml:
<string name=“hello”>Hello world</string>
Now I want to set a value to a TextView using this string. Should I do it in java class like this:
TextView msgTextView = (TextView) findViewById(R.id.msg);
msgTextView.setText(R.string.hello);
or in xml file like below?
android:text="#string/hello"
Which approach is better? Or when it is better to use the first way and when the second one?
You should do neither. There is relatively new approach , called databinding (it was demo in 2015) and now this library is officially supported by Google. It is a manifestation of MVVM pattern and you should use it, because it limplifies your code and makes it more maintainable in long term. See https://developer.android.com/topic/libraries/data-binding/index.html . In few words- you create Java class with fields and accessirs and set its fields as xml attributes. By doing so, AndroidStudio will generate all .findViewbyId() boilerplate for you. you just create model and set it to that particular binding.
Regarding performance, it won't make any difference. I personally prefer to do it in XML, since it doesn't clutter your activity code.
Both approach is correct. If you want to internationalize your variable that time (change languages) both will be work. In reference of memory or speed dynamically change is correct(means using getResource() or R.string.hello).
at first you should set it in xml.(or leave it empty.) but if you want to change it when something else happens (for example when user click a button or anything else.) you should set it in java.
First method is generally used when you want your textview to be fixed and final .
Second method is recommended as the textview's value may change during the course of operation of app .Initially in second method , a value is shown by textview which shows its purpose or type . For e.g second one may be used in displaying progress of background task .
I'm new to Android development and I'm trying to make a calculator app in AndroidStudio. Originally, I used Buttons, and to retrieve the number of a button pressed, the function btn.getText() worked perfectly. I've since replaced the Buttons with ImageButtons, with the number now represented in the image.
My plan was to give all ImageButtons ids in the vein of 'btn0', 'btn1', and so on, then do something like
Character number = imgbtn.getId().charAt(imgbtn.length()-1);. This, however, fails miserably, as the id is apparently an automatically assigned int, and not the id I set.
Is there a way to access the string id property that I defined?
Alternatively, I saw mention of a getTag() function in my prior googling for solutions that looks like it might be useful in this situation, but I can't find an ImageButton tag property where I can set it.
Solved my specific issue: I just discovered that I can set the tag in the Text view, by adding android:tag="x" to the relevant ImageButtons (or that I could call imgbtn.setTag() to the same effect). I'm going to submit this anyway, in case someone has a similar issue in the future.
Lingering Questions
My question about accessing one's defined string id still stands. Is there a way to do that, in case I'd ever like to?
Also, what's an Object Tag, such as it would be used in imgbtn.setTag(<Object tag>)? I can't find any documentation.
At compile time, all resources are compiled in to a class called R.Java. When you say findViewById(R.id.xxx) what you are actually doing is pointing to a static reference of a final integer called "xxx" that has been hardcoded into this Java file. If you'd like to view this, navigate to the build directory after you've built your project and go to generated, source, debug (or release) then through your project until you see R.java
In other words, the String of the id is not present at runtime.
This is a general question about the efficiency of hardcoding data - I'm writing a program in Java that does some chemical analysis, and I need to use the isotopic abundances of different elements. The way I have it set up right now is that all values (which never need to be modified) are stored as final fields in my class, i.e.
static final double C12Abundance = .989;
static final double C12Mass = 12;
A lot of similar programs store this type of data in an XML file, then read the values from there, like this:
<compounds>
<elements>
<element symbol='C' mono_isotopic_mass ='12.00000000000' abundance='.989'/>
Is there any reason (performance, memory, etc) to read from it this way? Seems easier to just leave it as a field.
Hard coding is way much faster in terms of performance and memory allocation.
The thing you gain from reading from a file is code re-usability (running your program with different parameters without the need to recompile it).
Note that reading from a file has the following steps:
Declare variable to use for storing a value.
Create an input (stream) object
Initialize it with a path
Open The file from FS
Find the correct line to read from
Read the value
Store it in the variable above
Close the input (stream)
That's a pretty big overhead instead of having a pre-compiled final variable with a value
As these are truely universal constants, properties limited in number, you can put them in code, but nicely organized.
public enum Element {
// Name Mass Abund
C12("C", 12.0, .989),
He4(...),
O32(...),
...;
public final String name;
public final double monoIsotopicMass;
public final double abundancy;
private Element(String name, double monoIsotopicMass, double abundancy) {
this.name = name;
this.monoIsotopicMass = monoIsotopicMass;
this.abundancy = abundancy;
}
}
for (Element elem : Element.values()) {
if (elem.abundancy > 0.5) {
...
}
}
If you want to hard-code the values and want to change them, you have to recompile your program, that's the problem. Reading your data from a file have the following benefits:
You don't have to wait for the program to recompile for every change in the data. For a fairly large program, this can take time.
Your users can change the data without even having access to the source.
You can have different data sets between which you can switch just by changing the config file name.
Maybe none of this matter to you; then just go ahead and put your data in the source.
Performance itself (as in the performance of the program) is never a problem except if your profiler says so. But I don't see how reading for the data file at startup a small set of data could be a long process, so I'm fairly sure you would'nt see a difference.
If you want so simulate a universe with a different abundance of C12, having the values hard coded would mean you have to recompile the program.
There may be other reasons as well: if the values are read from an external file the file serves as documentation, an external file may be easier to check for errors, there may be tools that generate the file or use it for other purposes besides running your program, ...
A configuration file holds properties, generally speaking these properties are changing in time. I believe that in your case those are fixed and will never change, by definition.
For this reason I would do the easier thing possible, which is leaving them as fields.
This is not a performance matter, as long as performance doesn't show up being an issue, this is just a matter of what is more easily usable in your codebase.
I would advice you to extract these values in a class as constants, so you could always import it to access the values.
The Java code in only readable by a Java compiler whereas XML is readable by any reasonable (meaning XML aware) language. Also If you want to add some value, you don't have to recompile everything.
Personally I'd go for hardcoding if the values are not gonna be changed ever and if the app is small. Otherwise I would choose external sources of conf data.
But everytime people tell me that values are not gonna change, it pretty much means that they will so preparing dynamic environments is the way to go in general. XML conf files, database conf tables etc.
If you write them in XML you can use different values for different devices,
e.g assume you have a dimension with name item_margin and it needs to be different based on width of device so in values/dimens.xml you have this
<dimen name="item_margin">0dp</dimen>
and in devices which has min 600dp width you want this margin to be 60dp so in
values-sw600dp/dimens.xml you have this
<dimen name="item_margin">60dp</dimen>
in this way these values are automatically selected based on device width, thus you don't have to check the device width and select appropriate value in your Java code