使用已儲存的值   Android Jetpack 的一部分。

本主題說明如何儲存及使用保存於偏好設定資料庫的 Preference 值。

Preference 資料儲存

本節說明 Preference 如何保存資料。

SharedPreferences

根據預設,Preference 會使用 SharedPreferences 來儲存值。SharedPreferences API 可讓您在不同的應用程式工作階段中,從儲存的檔案讀取及寫入簡單的鍵/值組合。偏好設定資料庫使用私人 SharedPreferences 執行個體,因此只有您的應用程式才能存取。

舉例來說,假設 SwitchPreferenceCompat 如下:

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

使用者將此設定切換為 On 狀態時,SharedPreferences 檔案即會更新為 "notifications" : "true" 的鍵/值組合。請注意,使用的鍵即是為 Preference 設定的鍵。

如要進一步瞭解 SharedPreferences API,請參閱「儲存鍵/值資料」。

如要瞭解在 Android 上儲存資料的各種方式,請參閱「資料和檔案儲存空間總覽」。

PreferenceDataStore

雖然偏好設定資料庫根據預設使用 SharedPreferences 保留資料,但 SharedPreferences 不一定是理想的解決方案。例如,如果應用程式要求使用者登入,則建議您將應用程式設定保留在雲端,使設定在其他裝置和平台也保持一致。同樣地,如果應用程式有裝置專屬的設定選項,則裝置上的每位使用者都會有不同設定,因此 SharedPreferences 並不理想。

PreferenceDataStore 可讓您使用自訂儲存空間後端來保留 Preference 值。詳情請參閱使用自訂資料儲存區

讀取 Preference 值

如要擷取目前使用的 SharedPreferences 物件,請呼叫 PreferenceManager.getDefaultSharedPreferences()。在應用程式的任何位置皆可使用這種方法。例如,假設 EditTextPreference 含有 "signature" 索引鍵:

<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
每個偏好設定分別設定 套用至所有偏好設定
在偏好設定即將變更儲存的值時呼叫,這包括待處理的值是否與目前儲存的值相同。 只有在偏好設定的儲存值變更時才會呼叫。
只能透過偏好設定資料庫呼叫。應用程式的個別部分可能會變更儲存的值。 每當儲存的值發生變更時都會呼叫,即使值來自應用程式個別部分也是如此。
在儲存待處理的值之前呼叫。 在儲存值之後呼叫。
在使用 SharedPreferencesPreferenceDataStore 時呼叫。 僅在使用 SharedPreferences 時呼叫。

OnPreferenceChangeListener

您可以透過實作 OnPreferenceChangeListener 監聽 Preference 的值何時將要變更,然後驗證是否應發生此變更。例如,以下程式碼示範如何監聽含有「名稱」索引鍵的 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 儲存的值何時變更,例如在與伺服器同步設定時變更。以下範例說明如何監聽含有「名稱」索引鍵的 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 設定的資料儲存區,會覆寫為相應階層設定的任何資料儲存區。大部分情況下,您都應為整個階層設定資料儲存區。