当Android用户偏好设置结构在新版本中发生更改时,现有数据会发生什么变化?

9
例如,如果增加或删除了几个偏好设置条目,当应用程序使用新的偏好设置结构进行更新时,Android如何处理现有的偏好设置数据?
对于这个基础的问题,我很抱歉,但是我通过认真搜索和阅读无法找到答案。

如果您愿意,您可以从DDMS中提取prefs XML文件并自行查看。 - mango
2个回答

6
共享偏好设置存储在文件夹data/data/your.application.package/shared_prefs/中的xml文件中。该文件名为your.application.package_preferences.xml
当您检索共享偏好设置时,调用Context.getSharedPreferences方法。它创建SharedReferences对象并调用SharedReferences.startLoadFromDisk方法。
如果您打开此方法,您将看到偏好设置的xml文件(mFile)被解析并将偏好设置加载到内存存储器(map)中。
BufferedInputStream str = new BufferedInputStream(new FileInputStream(mFile), 16*1024);
map = XmlUtils.readMapXml(str);

从那时起,您将始终从内存中读取您的首选项。更确切地说,从private Map<String, Object> mMap变量中读取。此外,应用程序可以调用startReloadIfChangedUnexpectedly方法,如果底层文件已更改,则会解析该文件并创建一个新HashMap。
至于您的问题,有以下情况:
1. 您在新版本中添加了首选项项。然后默认值将作为第二个参数返回。注意:未使用android:defaultValue属性,请注意。 String v = (String)mMap.get(key); // 未找到 => v = null return v != null ? v : defValue; // 返回defValue 2. 您在新版本中删除了首选项项。xml文件和map对象将包含一些冗余数据,但当用户下次保存首选项时,它将被修复。
3. 您将首选项项的键更改为未使用的某个键。然后默认值将被返回。与情况1相同的结果。
4. 您删除了一个首选项项(例如带有键pref1_key),并更改了另一个项的键,使其引用第一个项(从pref2_keypref1_key)。那么第二个首选项项将具有第一个项的值。
5. 您更改了首选项项的类型(例如从boolean更改为int)。然后它将抛出CastException,因为类似(Integer)mMap.get(key);的代码。但是您可以将EditTextPreference更改为ListPreference,因为它们都具有String类型。
也许还有一些其他测试用例,但是到目前为止,我只想到了5个。
此外,这里是具有ListPreference、EditTextPreference和CheckBoxPreference的首选项文件示例:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="pref_theme_key">THEME_LIGHT</string>
    <string name="pref_homepage_key">test</string>
    <boolean name="pref_display_name_key" value="true" />
</map>

非常感谢您提供详细的答案。您列举的情况恰好是我所思考的。我认为在应用程序开发过程中更改首选项结构是一个相当普遍的场景,但是在Android文档中找不到任何相关内容。也许我没有看对文档。 - Hong
2
@Hong 有时候官方文档里并没有信息,这时我会使用grepcode网站并自己检查源代码。 - vortexwolf

2
当应用程序使用新的首选项结构进行更新时,Android如何处理现有的首选项数据?
“Preferences结构”指的是什么还不确定。你可以将SharedPreferences视为持久性HashMap。您可以在各种键下存储各种值,并且以后可以获取它们。直到您实际存储某些内容之前,Android没有关于键或存储在这些键下的值类型的先验知识。
我猜你所说的“首选项结构”是指“XML中的首选项屏幕定义”。在这种情况下:
- 如果添加了新的首选项,则Android将正常处理这些首选项,就好像首选项一直存在,但用户以前从未设置过这些首选项。 - 如果删除了您以前使用过的首选项,则旧数据仍然存在,除非您选择摆脱它,因为Android无法知道您再也不会使用该数据。 - 如果重新对首选项进行密钥更改(例如,将keyA替换为逻辑上相同的首选项的key1),Android将把key1视为全新的首选项,因此您需要在代码中放置一些聪明的东西来更新您的SharedPreferences数据以反映密钥更改(如果您选择这样做)。
与SQLiteOpenHelper的SharedPreferencesOpenHelper版本不同,没有管理首选项“模式版本”的系统来帮助您迁移数据。如果您认为它将帮助您管理频繁更改的“首选项结构”,则可以创建这样的系统。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接