使用保存的偏好值   作为 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设置的数据存储会覆盖为相应层次结构设置的任何数据存储。在大多数情况下,您会为整个层次结构设置数据存储。