使用已儲存的偏好設定值 Android Jetpack 的一部分。

本文說明如何儲存及使用 Preference 程式庫儲存的 Preference 值。

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()。雖然這種方法可以在應用程式的任意位置運作,但我們還是建議您將應用程式分割為多個層。詳情請參閱資料層

例如,假設 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
在單一 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 設定的資料儲存庫,會覆寫為對應階層設定的任何資料儲存庫。在大多數情況下,您會為整個階層設定資料儲存庫。