使用保存的值   Part of Android Jetpack.

本主题将介绍如何存储和使用 Preference Library 保存的 Preference 值。

首选项数据存储

本部分介绍 Preference 如何保留数据。

SharedPreferences

默认情况下,Preference 使用 SharedPreferences 保存值。 SharedPreferences API 支持从在各个应用会话中保存的文件中,读取和写入简单的键值对。

Preference Library 使用不公开的 SharedPreferences 实例,因此只有您的应用可以访问该库。

举例来说,我们假设以下 SwitchPreferenceCompat

<SwitchPreferenceCompat
        app:key="notifications"
        app:title="Enable message notifications"/>

如果用户将此开关切换至 On 状态,则 SharedPreferences 文件使用 "notifications" : "true" 键值对更新。 请注意,所用密钥与为 Preference 设置的密钥一致。

如需更多有关 SharedPreferences API 的信息,请参阅 保存键值数据

如要详细了解在 Android 上存储数据的不同方法,请参阅 数据和文件存储概览

PreferenceDataStore

虽然 Preference Library 默认保留含有 SharedPreferences 的数据,但 SharedPreferences 不一定总是理想的解决方案。 例如,如果应用需要用户登录,您可能希望在云中保留应用设置,以便设置能够映射在其他设备和平台上。 同理,如果您的应用有设备特定的配置选项,则设备上的每个用户都可能有单独的设置,从而使 SharedPreferences 成为不甚理想的解决方案。

PreferenceDataStore 使您能够使用自定义存储空间后端保留 Preference 值。 如需更多信息,请参阅 使用自定义数据存储

读取首选项值

要检索正在使用的 SharedPreferences 对象,请调用 PreferenceManager.getDefaultSharedPreferences()。 此方法适用于您应用的任何位置。 例如,给定一个密钥为“signature”的 EditTextPreference

<EditTextPreference
        app:key="signature"
        app:title="Your signature"/>

您可以对此 Preference 的保存值进行全局检索,方法如下:

Kotlin

val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */)
val name = sharedPreferences.getString("signature", "")

Java

SharedPreferences sharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
String name = sharedPreferences.getString(“signature”, "");

侦听首选项值的变化

要侦听 Preference 值的变化,您可以在两个接口中选择一个:

下表展示了两个接口的差别:

OnPreferenceChangeListener OnSharedPreferenceChangeListener
针对每个首选项进行设置 应用于所有首选项
在首选项要改变其保存的值时进行调用。 如果待处理的值与当前保存的值相同,则其也包括在内。 只在为首选项保存的值发生变化时调用。
只通过 Preference Library 调用。 应用的单独部分可以改变保存的值。 随保存值的变动进行调用,即便该值来自应用的单独部分也是如此。
在待处理的值保存前调用。 在该值保存后调用。
在使用 SharedPreferencesPreferenceDataStore 时调用。 只在使用 SharedPreferences 时调用。

OnPreferenceChangeListener

执行 OnPreferenceChangeListener 使您能够侦听Preference 的值将在何时出现变动。 由此,您可以验证此变动是否应该发生。 例如,以下代码展示了如何侦听密钥为“name”的 EditTextPreference 值的变化:

Kotlin

override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
    Log.e("preference", "Pending Preference value is: $newValue")
    return true
}

Java

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    Log.e("preference", "Pending Preference value is: " + newValue);
    return true;
}

接下来,您需要直接使用 setOnPreferenceChangeListener() 设置此侦听器,如下所示:

Kotlin

preference.onPreferenceChangeListener = ...

Java

preference.setOnPreferenceChangeListener(...);

OnSharedPreferenceChangeListener

在使用 SharedPreferences 保留 Preference 值时,您还可以使用 SharedPreferences.OnSharedPreferenceChangeListener 侦听变动。 这使您能够侦听 Preference 保存的值在何时出现变动,例如在与服务器同步设置时。 以下示例展示了如何侦听密钥为“name”的 EditTextPreference 值 出现变动的时间:

Kotlin

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
    if (key == "signature") {
        Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, ""))
    }
}

Java

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals(“signature”)) {
        Log.i(TAG, “Preference value was updated to: “ + sharedPreferences.getString(key, ""));
    }
}

此外,您必须通过 registerOnSharedPreferenceChangedListener() 注册侦听器,如下所示:

Kotlin

preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(...)

Java

getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(...);

Kotlin

val listener: SharedPreferences.OnSharedPreferenceChangeListener =
        SharedPreferences.OnSharedPreferenceChangeListener {...}

Java

SharedPreferences.OnSharedPreferenceChangeListener listener =
        new SharedPreferences.OnSharedPreferenceChangeListener() {...}

为妥善管理 ActivityFragment 的生命周期,您应使用 onResume()onPause() 回调完成此侦听器的注册和取消注册,如下所示:

Kotlin

override fun onResume() {
    super.onResume()
    preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}

override fun onPause() {
    super.onPause()
    preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
}

Java

@Override
public void onResume() {
    super.onResume();
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause() {
    super.onPause();
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

使用自定义数据存储

虽然推荐使用 SharedPreferences 保留 Preference,但您也可以使用自定义数据存储。 如果您的应用将值保留至数据库,又或者值专门针对设备,这时自定义数据存储会非常有用,如示例所示。

采用数据存储

要采用自定义数据存储,先要创建一个扩展 PreferenceDataStore 的类。 以下示例创建了一个处理 String 值的数据存储:

Kotlin

class DataStore : PreferenceDataStore() {
    override fun putString(key: String, @Nullable value: String) {
        // Save the value somewhere
    }

    @Nullable
    override fun getString(key: String, @Nullable defValue: String): String {
        // Retrieve the value
    }
}

Java

public class DataStore extends PreferenceDataStore {
    @Override
    public void putString(String key, @Nullable String value) {
        // Save the value somewhere
    }
    @Override
    @Nullable
    public String getString(String key, @Nullable String defValue) {
        // Retrieve the value
    }
}

确保不在主线程上执行任何耗时操作,以避免堵塞用户接口。 由于在保留值的过程中,包含数据存储的 FragmentActivity 可能会被销毁,所以您应该将数据序列化,以防丢失用户更改的任何值。

启用数据存储

采用数据存储后,您必须在 onCreatePreferences() 中设置新的数据存储,以便 Preference 对象使用数据存储保留值,而非使用默认的 SharedPreferences。 您可以针对每个 Preference 或整个层次结构启用数据存储。

要为特定 Preference 启用自定义数据存储,请调用 Preference 上的 setPreferenceDataStore(),如以下示例所示:

Kotlin

val preference = findPreference("key")
preference.preferenceDataStore = dataStore

Java

Preference preference = findPreference(“key”);
preference.setPreferenceDataStore(dataStore);

要为整个层次结构启用自定义数据存储,请调用 PreferenceManager 上的 setPreferenceDataStore()

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(dataStore);

为特定 Preference 设置的数据存储将替换为对应层次结构设置的任何数据存储。 大多数情况下,您需要为整个层次结构设置一个数据存储。