To store an integer in an Android preference, I would intuitively go for EditTextPreference and do the usual String-int-String conversions.
But then I came across a piece of code that stores an integer in a <ListPreference> instead:
<ListPreference
android:key="@string/total_score"
android:defaultValue="0" />
and retrieves it using preferences.getInt(getString(R.string.total_score), 0);
Does this really work? If so, how?
Is it considered acceptable practice?
UPDATE: Thanks to the answers below, I have been able to find the implementation source code for getInt(). I am posting it here for easy reference:
jint android::content::SharedPreferences::getInt(local_ref< java::lang::String > const &a0, jint a1)
{
return call_method<
android::content::SharedPreferences::J2CPP_CLASS_NAME,
android::content::SharedPreferences::J2CPP_METHOD_NAME(2),
android::content::SharedPreferences::J2CPP_METHOD_SIGNATURE(2),
jint
>(get_jobject(), a0, a1);
}
In theory, yes you can store an integer with a ListPreference. After all it's a UI-preference that maps a user displayed label/key (android:entries) to an internal value (android:entryValues) and displays all those mapping options in a listview. That internal value might as well be an integer. You could use a <integer-array>-resource for the entryValues.
In practice, I've never seen that work - it's bugged.
Of course, you can set a int value to the preference key of the ListPreference in your code, since it's a normal preference internally. But that would defeat the whole purpose of predefined resource arrays and ability to select from a list. As a workaround, if a int-array would be handy, I recommend using a <string-array> for the values and convert them an integer in code, as you would with your EditTextPreference
Check this question for a non-working example. ;)
To answer your title question which one to choose for an integer: Depends.
You can use either one with the workarounds.
If the user should be able to enter any value (or just a lot of values), the EditTextPreference is the way to go. A ListPreference would just be too long.
If you have a small set of predefined ints, use a ListPreference. Thats way more comfortable to use and might be displayed with useful labels. Example: If the user is supposed to select a timing interval, you could map the seconds in the value and display a different label, e.g. an hour [value 3600; label "Hour"].
Edit: Also got an idea where your code snippet may be related to. Since this ListPreference does neither specify android:entries nor android:entryValues, it might just be part of a default preference file. You can use PreferenceManager.setDefaultValues() with an XML file to reset/initalize all your preference keys. In this case it's completely random which preference you choose, because all fields that count are android:key and android:defaultValue. You might use any other type in this case, does not matter.
I think what's going on is that the ListPreference is storing the entry values as an array of chars, or in other words an array of bytes (I'm inferring this from the setEntryValues(CharSequence[] entryValues) method). This could be why storing a number works, because the value is stored into the byte array, so using the preferences.getInt(...) method will still work. This could be dangerous, however, as discrepancies with signing could occur, so I wouldn't recommend it, and would parse the int from a string preference instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With