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