保存されている値を使用する   Android Jetpack の一部

このトピックでは、Preference ライブラリによって保存される Preference 値を格納および使用する方法について説明します。

Preference のデータ保存

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

SharedPreferences

デフォルトでは、PreferenceSharedPreferences を使用して値を保存します。SharedPreferences API を使用すると、アプリの複数のセッションにまたがって、保存ファイルに対して単純な Key-Value ペアの書き込みと読み取りを行うことができます。 Preference ライブラリは、非公開の SharedPreferences インスタンスを使用して、目的のアプリだけがこのインスタンスにアクセスできるようにします。

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

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

ユーザーがこのスイッチを On に切り替えると、"notifications" : "true" という Key-Value ペアで SharedPreferences ファイルが更新されます。使用されるキーは、Preference 用に設定されているキーと同じです。

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

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 値の変更をリッスンするには、次の 2 つのインターフェースのいずれかを選択します。

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

OnPreferenceChangeListener OnSharedPreferenceChangeListener
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);
}

カスタム データストアの使用

Preference オブジェクトの保持には SharedPreferences を使用することが推奨されますが、カスタム データストアも使用できます。カスタム データストアは、アプリがデータベースに値を保持する場合や、値がデバイスに固有の場合などに便利です。

データストアを実装する

カスタム データストアを実装するには、まず、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() で新しいデータストアを設定する必要があります。これにより、Preference オブジェクトは、デフォルトの SharedPreferences を使用する代わりにデータストアを使用して、値を保持するようになります。データストアは、Preference ごとに有効にすることも、階層全体で有効にすることもできます。

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

Kotlin

val preference: Preference? = findPreference("key")
preference?.preferenceDataStore = dataStore

Java

Preference preference = findPreference(“key”);
if (preference != null) {
    preference.setPreferenceDataStore(dataStore);
}

階層全体でカスタム データストアを有効にするには、PreferenceManagersetPreferenceDataStore() を呼び出します。

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(dataStore);

特定の Preference 用に設定されているデータストアは、対応する階層用に設定されているデータストアをすべてオーバーライドします。ほとんどの場合、階層全体でデータストアを設定する必要があります。