使用保存的 Preference 值   Android Jetpack 的一部分。

本文档介绍了如何存储和使用 Preference 库保存的 Preference 值。

Preference 数据存储

本节介绍了 Preference 如何持久化数据。

SharedPreferences

默认情况下,Preference 使用 SharedPreferences 保存值。SharedPreferences API 支持从跨应用会话保存的文件中读取和写入简单的键值对。Preference 库使用私有的 SharedPreferences 实例,以便只有您的应用可以访问它。

例如,假设以下 SwitchPreferenceCompat

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

当用户将此开关切换到“开启”状态时,SharedPreferences 文件会更新,其中包含键值对 "notifications" : "true"。使用的键与为 Preference 设置的键相同。

如需详细了解 SharedPreferences API,请参阅保存键值数据

如需了解在 Android 上存储数据的不同方式,请参阅数据和文件存储概览

PreferenceDataStore

虽然 Preference 库默认使用 SharedPreferences 持久化数据,但 SharedPreferences 并非总是理想的解决方案。例如,如果您的应用要求用户登录,您可能希望将应用设置持久化到云端,以便设置反映在其他设备和平台上。同样,如果您的应用具有特定于设备的配置选项,则设备上的每个用户都有单独的设置,这使得 SharedPreferences 成为一个不那么理想的解决方案。

PreferenceDataStore 允许您使用自定义存储后端来持久化 Preference 值。如需了解详情,请参阅使用自定义数据存储

读取 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 值变化

要监听 Preference 值的变化,您可以选择以下两个接口

下表显示了两个接口的区别

OnPreferenceChangeListener OnSharedPreferenceChangeListener
设置在单个 Preference 上。 适用于所有 Preference 对象。
Preference 即将更改其保存值时调用,即使待处理值与保存值相同。 仅在 Preference 的保存值发生变化时调用。
仅通过 Preference 库调用。应用的其他部分可以更改保存值。 每当保存值发生变化时调用,即使来自应用的其他部分。
在待处理值保存之前调用。 在值保存之后调用。
使用 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, value: String?) {
        // Save the value somewhere.
    }

    override fun getString(key: String, 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: Preference? = findPreference("key")
preference?.preferenceDataStore = dataStore

Java

Preference preference = findPreference("key");
if (preference != null) {
    preference.setPreferenceDataStore(dataStore);
}

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

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

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

为特定 Preference 设置的数据存储将覆盖为相应层级结构设置的任何数据存储。在大多数情况下,您会为整个层级结构设置数据存储。