Stay organized with collections Save and categorize content based on your preferences.

使用已儲存的值   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 設定的資料儲存區,會覆寫為相應階層設定的任何資料儲存區。大部分情況下,您都應為整個階層設定資料儲存區。