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

烈酒焚心 提交于 2019-12-23 09:57:54

问题


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?


回答1:


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.



回答2:


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.




回答3:


SharedPreferences is an abstraction over Key/Value databasing provided by Google, how you use it is up to you. If you dislike this syntax, then create a wrapper or extension for your getString(). Just to give an example:

fun PreferenceManager.getStringTheFancyWay(key: String, defaultValue: String): String {
    return getString(key, defaultValue) ?: defaultValue
}
val value = getStringTheFancyWay("a", "b")

Personally I dislike this, because null allows for a better control flow over non-existing keys.

This is how I use SharedPreferences

val preferences = PreferenceManager.getDefaultSharedPreferences(context)
val value = preferences.getString("username", null)
if (value != null) {
    toast("Hello $value")
} else {
    toast("Username not found")
}

or

preferences.getString("username", null)?.let { username ->
    toast("Hello $username")
}

Notice the difference?




回答4:


The fact is simple, just imagine you haven't saved any value regarding to that key(for your case 'MyKey') and tried to get the value for that key(for your case 'MyKey'). What will SharedPreference return ? It will simply return the default value.

You will see that, you must assign null or any other string to default for String type, 0 or any other int value to default for integer type and true or false default value for bolean type. I hope you got the answer.



来源:https://stackoverflow.com/questions/57318576/whats-the-point-of-having-a-default-value-in-sharedpref-getstring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!