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

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

偏好数据存储

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

SharedPreferences

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

例如,假设以下 SwitchPreferenceCompat

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

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

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

有关在 Android 上存储数据的不同方法的信息,请参阅 数据和文件存储概述

PreferenceDataStore

尽管偏好库默认使用 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 上。 适用于所有 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.
    }
}

在主线程之外运行任何耗时的操作,以避免阻塞用户界面。由于 Fragment 或包含数据存储的 Activity 可能在持久化值时被销毁,因此请序列化数据,这样您就不会丢失用户更改的任何值。

启用数据存储

在实现数据存储后,请在 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 设置的数据存储会覆盖为相应层次结构设置的任何数据存储。在大多数情况下,您会为整个层次结构设置数据存储。