LoginSignup
5
2

More than 5 years have passed since last update.

SharedPreferencesのラッパークラスを作ろう

Posted at

これはAndroidその2 Advent Calendar 2016 12/20の投稿です。

はじめに

今回はキーと値のペアを保存、取得することができるSharedPreferencesをより安全、簡単に使うためにラッパークラスを作る話をします。
基本的な話となるため、SharedPreferencesの使用における自分なりのプラクティスが無い人向けの投稿となります。
ご了承ください。

基本的なSharedPreferences使用法の再確認

標準的なSharedPreferencesを使用した値の書き込み、及び読み出しは以下のコードとなるかと思われます。

SharedPreferences sp = context.getSharedPreferences("hoge", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("fuga", false);
editor.apply();
SharedPreferences sp = context.getSharedPreferences("hoge", Context.MODE_PRIVATE);
boolean fuga = sp.getBoolean("fuga", false);

問題点

上記コードから問題点を洗い出してみます。
1. getSharedPreferences, putBoolean, getBooleanメソッドの第一引数を忘れたり、スペルミスしたりしてしまう可能性がある。
2. applyメソッドを呼び忘れる可能性がある。
3. 全体的にもっとスマートに記述したい。

とりあえずはこのくらいでしょうか。
早速問題解決していきましょう。

実践

データファイルをenum管理

まずSharedPreferencesのデータファイルをenumで管理します。

PreferenceNames.java
public enum PreferenceNames {
    DEFAULT("default");
    HOGE("hoge");

    private final String name;

    PreferenceNames(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

データファイルを増やしたい場合は、このenumに追加するだけです。
簡単ですね。

SharedPreferencesのラッパークラスを作成する

次に、上記enumを取り扱うことが出来るようにSharedPreferencesのラッパークラスを作成し、コンストラクタを記述します。

MySharedPref.java
public class MySharedPref{
    private final SharedPreferences sp;
    private final PreferenceNames preferenceNames;

    public MySharedPref(Context context, PreferenceNames preferenceNames) {
        if (preferenceNames == PreferenceNames.DEFAULT) {
            this.sp = PreferenceManager.getDefaultSharedPreferences(context);
        } else {
            this.sp = context.getSharedPreferences(preferenceNames.getName(), Context.MODE_PRIVATE);
        }
        this.preferenceNames = preferenceNames;
    }
}

ここでは、第二引数にPreferenceNames.DEFAULTを設定した場合はgetDefaultSharedPreferencesメソッドをコールします。

これでgetSharedPreferencesメソッドの第一引数の忘れ、及びスペルミス問題は解決しました。

キーのenum管理

次に、キーをenumで管理します。

PreferenceKeys.java
public enum PreferenceKeys {
    FUGA(PreferenceNames.HOGE, Boolean.class, true);

    private final PreferenceNames preferenceNames;
    private final Class<?> valueClass;
    private final String key;

    PreferenceKeys(PreferenceNames preferenceNames, Class<?> valueClass, String key) {
        this.preferenceNames = preferenceNames;
        this.valueClass = valueClass;
        this.key = key;
    }

    public PreferenceNames getPreferenceNames() {
        return preferenceNames;
    }

    public Class<?> getValueClass() {
        return valueClass;
    }

    public String getKey() {
        return key;
    }
}

SharedPreferencesのキーを増やしたい場合は、このenumに追加するだけです。
一列でそのキーが何のデータファイルで使用され、紐付けられる値のクラスは何かを把握することが出来るという点でもこのenumは優れています。

putXXXメソッドの作成

putBooleanメソッドを以下のように作成します。

MySharedPref.java
public void putBoolean(PreferenceKeys preferenceKeys, boolean value) {
    if (preferenceKeys.getPreferenceNames() == preferenceNames && preferenceKeys.getValueClass() == Boolean.class) {
        sp.edit().putBoolean(preferenceKeys.getKey(), value).apply();
    } else {
        throw new IllegalArgumentException();
    }
}

同時にapplyメソッドの呼び出し忘れ問題も解決することが出来ました。
一度にたくさんの値を保存する場合はまた別のソリューションを考える必要がありますが、値を一度に変更するような機能に関して、SharedPreferencesはあまり使用されないでしょう。

getXXXメソッドの作成

getBooleanメソッドは以下のように作成します。

MySharedPref.java
public boolean getBoolean(PreferenceKeys preferenceKeys) {
    if (preferenceKeys.getPreferenceNames() == preferenceNames && preferenceKeys.getValueClass() == Boolean.class) {
        return sp.getBoolean(preferenceKeys.getKey(), false);
    } else {
        throw new IllegalArgumentException();
    }
}

こちらも初期値を都度変更したい場合は、引数として渡してあげるといいでしょう。
そこら辺は人やプロジェクトによると思われるため、自由にカスタマイズしてみてください。

また、putXXX, getXXXメソッドはboolean以外にもStringやintなどが必要になるはずですので、同様に実装してみてください。

おまけ

ついでにclearメソッドも作成してみましょう。

MySharedPref.java
public void clear() {
    sp.edit().clear().apply();
}

ラッパークラスとenumの作成は以上です。

比較

以下、ラッパークラスを使わないバージョンと使うバージョンでデータの書き込み、及び読み出しのサンプルを比較してみました。

// Use no wrapper
SharedPreferences sp = context.getSharedPreferences("hoge", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putBoolean("fuga", false);
editor.apply();

// Use wrapper
MySharedPref sp = new MySharedPref(this, PreferenceNames.HOGE);
sp.putBoolean(PreferenceKeys.FUGA, true);
// Use no wrapper
SharedPreferences sp = context.getSharedPreferences("hoge", Context.MODE_PRIVATE);
boolean fuga = sp.getBoolean("fuga", false);

// Use wrapper
MySharedPref sp = new MySharedPref(getActivity(), PreferenceNames.HOGE);
boolean fuga = sp.getBoolean(PreferenceKeys.FUGA);

まとめ

さて、ラッパーを作る意義が感じられましたでしょうか。
今回は、基本的な機能しか実装していませんが、個人個人でカスタマイズして自分なりのSharedPreferencesラッパークラスを作成してみてください。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2