保存した設定値を使用する Android Jetpack の一部

このドキュメントでは、Preference ライブラリによって保存される Preference 値を格納して使用する方法について説明します。

Preference のデータ保存

このセクションでは、Preference でのデータの保持方法について説明します。

SharedPreferences

デフォルトでは、PreferenceSharedPreferences を使用して値を保存します。SharedPreferences API は、アプリ セッションをまたいで保存されるファイルに対して、シンプルな Key-Value ペアの読み取りと書き込みをサポートします。Preference ライブラリは、アプリのみがアクセスできるように、プライベート SharedPreferences インスタンスを使用します。

たとえば、次のような SwitchPreferenceCompat があるとします。

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

ユーザーがこのスイッチを「オン」状態に切り替えると、SharedPreferences ファイルが Key-Value ペア "notifications" : "true" に更新されます。使用される鍵は、Preference に設定された鍵と同じです。

SharedPreferences API の詳細については、Key-Value データを保存するをご覧ください。

Android でデータを保存するさまざまな方法については、データ ストレージとファイル ストレージの概要をご覧ください。

PreferenceDataStore

Preference ライブラリは、デフォルトでは SharedPreferences を使用してデータを保持しますが、SharedPreferences は必ずしも理想的なソリューションではありません。たとえば、ユーザーがログインする必要があるアプリの場合は、アプリの設定をクラウドに残して、設定が他のデバイスやプラットフォームにも反映されるようにすることをおすすめします。同様に、アプリにデバイス固有の構成オプションがある場合、デバイス上の各ユーザーが個別の設定を行うため、SharedPreferences は理想的なソリューションとは言えません。

PreferenceDataStore を使用すると、カスタム ストレージ バックエンドを使用して 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 値の変更をリッスンするには、次の 2 つのインターフェースのいずれかを選択します。

次の表に、2 つのインターフェースの違いを示します。

OnPreferenceChangeListener OnSharedPreferenceChangeListener
1 つの Preference で設定します。 すべての Preference オブジェクトに適用されます。
保留中の値が保存済みの値と同じであっても、Preference が保存されている値を変更しようとしたときに呼び出されます。 Preference に保存されている値が変更された場合にのみ呼び出されます。
Preference ライブラリを介してのみ呼び出されます。アプリの別の部分で、保存された値を変更できます。 保存された値が変更されるたびに呼び出されます。アプリの別の部分からの値であっても呼び出されます。
保留中の値が保存される前に呼び出されます。 値の保存後に呼び出されます。
SharedPreferences または PreferenceDataStore の使用時に呼び出されます。 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() {...}
    

Activity または Fragment でライフサイクルを適切に管理するには、次の例に示すように、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.
    }
}

時間のかかる処理はメインスレッド以外で実行し、ユーザー インターフェースをブロックしないようにします。値の保持中にデータストアを含む Fragment または Activity が破棄される可能性があるため、データをシリアル化して、ユーザーが変更した値が失われないようにします。

データストアを有効にする

データストアを実装したら、onCreatePreferences() で新しいデータストアを設定し、デフォルトの SharedPreferences を使用する代わりに、Preference オブジェクトがデータストアで値を保持するようにします。データストアは、Preference ごとに有効にすることも、階層全体で有効にすることもできます。

特定の Preference でカスタム データストアを有効にするには、次の例に示すように、PreferencesetPreferenceDataStore() を呼び出します。

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 に対して設定されているデータストアは、対応する階層に設定されているデータストアをオーバーライドします。ほとんどの場合、階層全体に対してデータストアを設定します。