Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the point of having a default value in sharedPref.getString?

I'm accessing my Android apps SharedPreferences via

private val sharedPref = PreferenceManager.getDefaultSharedPreferences(context)`

and then attempting to get data from it using

val lat: String = sharedPref.getString("MyKey", "Default")

But this line gives me an error reading "Type mismatch. Required String, found String?"

According to the documentation the second parameter in the getString method says "Value to return if this preference does not exist. This value may be null."

So what's the point of having a default value then if the value can be null? I cannot seem to get the default value to ever be used and the only way I can get my code to work is to use the elvis operator and rewrite my code as:

val lat: String = sharedPref.getString("MyKey", "Default") ?: "Default"

Which looks ugly. Am I crazy? What am I missing?

like image 546
szaske Avatar asked Aug 02 '19 00:08

szaske


People also ask

What is a shared preference in android?

A SharedPreferences object points to a file containing key-value pairs and provides simple methods to read and write them. Each SharedPreferences file is managed by the framework and can be private or shared. This page shows you how to use the SharedPreferences APIs to store and retrieve simple values.

How to store value in SharedPreferences android?

To store values in shared preferences: SharedPreferences sp = PreferenceManager. getDefaultSharedPreferences(this); SharedPreferences. Editor editor = sp.


2 Answers

Consider this in a such way: Every String preference in SharedPreferences can exist or not and can be null or not. So the code

val lat: String = sharedPref.getString("MyKey", "Default") ?: "Not Set"

will return:

  • Default if the preference with this Key doesn't exists (means there is no mapping for this Key)
  • Not Set if the preference exists, but is null (mapping Key to null created)
  • any other value if the preference exists and the value of the mapping isn't null.

Update

Apparently, SharedPreferences are much less smart I thought it was. Having this code internally:

String v = (String)mMap.get(key);
return v != null ? v : defValue;

it will return null only if we'll pass null as a default value (and there were no value saved). This means we actually don't need an elvis option and we will not get "Not Set" value. This method returns nullable value, just because it allows you to pass nullable as a default value.

like image 172
Demigod Avatar answered Sep 19 '22 18:09

Demigod


It's because kotlin Null-Safety is kick in when reading the following code:

val lat: String = sharedPref.getString("MyKey", "Default")

if you visit the SharedPreferences code, you can see the following code:

@Nullable
String getString(String key, @Nullable String defValue);

which is give us a probability to use null as defValue parameter. So, Kotlin try to guard it and give you the matching error:

"Type mismatch. Required String, found String?"

You can fix the problem by enabling nullable for your String variable with:

val lat: String? = sharedPref.getString("MyKey", "Default")

though this against Kotlin type system purpose:

Kotlin's type system is aimed at eliminating the danger of null references from code, also known as the The Billion Dollar Mistake.

like image 34
ישו אוהב אותך Avatar answered Sep 17 '22 18:09

ישו אוהב אותך