2015年5月19日火曜日

未選択状態を持つデータをどう表現するか悩んだ話、その2 - SharedPreferences -

前回 の続きです。


1. enum 版で SharedPreferences

SharedPreferences.Editor には残念ながら putSerializable() 的なものがありません。そのため、putInt() なりを使わざるを得ません。

enum 版では
・enum から int に変換して SharedPreferences に保存
・SharedPreferences から取得した int の値を enum に変換
という処理が必要になります。

@zaki50 さんの gist を参考に前回のコードに合わせました。zaki50 さんいつもありがとう。 private static final String PREF_SIZE_KEY = "pref_size_key"; public static void saveSize(@NonNull Context context, @Nullable Size size) { final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context); final SharedPreferences.Editor editor = pref.edit(); if (size == null) { editor.remove(PREF_SIZE_KEY); } else { editor.putInt(PREF_SIZE_KEY, size.getValue()); } editor.apply(); } @Nullable public static Size getSavedSize(@NonNull Context context) { final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context); if (pref.contains(PREF_SIZE_KEY)) { int value = pref.getInt(PREF_SIZE_KEY, Size.SIZE_L); return Size.fromIntValue(value); } return null; } public enum Size { ... private volatile static SparseArray<Size> intToEnum; public static Size fromIntValue(int value) { if (intToEnum == null) { final SparseArray<Size> sizeSparseArray = new SparseArray<>(); final Size[] values = values(); for (Size size : values) { sizeSparseArray.append(size.getValue(), size); } // おまけ。値の重複チェックをしておく if (sizeSparseArray.size() != values.length) { throw new IllegalStateException("duplicate values in Size enum"); } intToEnum = sizeSparseArray; } final Size size = intToEnum.get(value); if (size == null) { throw new IllegalArgumentException("invalid value: " + value); } return size; } } SharedPreferences から取得した int の値を enum に変換するために、新しく fromIntValue() を追加しています。



2. class 版で SharedPreferences

class で実装した方はこんな感じになります。
変換用のメソッドを新しく用意することなく、int 値からそのまま Size に変換しています(valueOf()については前回のコード参照)。 private static final String PREF_SIZE_KEY = "pref_size_key"; public static void saveSize(@NonNull Context context, @Nullable Size size) { final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context); final SharedPreferences.Editor editor = pref.edit(); if (size == null) { editor.remove(PREF_SIZE_KEY); } else { editor.putInt(PREF_SIZE_KEY, size.getValue()); } editor.apply(); } @Nullable public static Size getSavedSize(@NonNull Context context) { final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context); if (pref.contains(PREF_SIZE_KEY)) { @ValidSize int value = pref.getInt(PREF_SIZE_KEY, Size.SIZE_L); return Size.valueOf(value); } return null; } SharedPreferences から読み出した値が @ValidSize である保証がないので、そこをチェックしたかったら enum 版と同じようなコンバーターか値のバリデータを介す必要があります。 @Nullable public static Size getSavedSize(@NonNull Context context) { final SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context); if (pref.contains(PREF_SIZE_KEY)) { int value = pref.getInt(PREF_SIZE_KEY, Size.SIZE_L); return Size.convertIntValue(value); } return null; } private static class Size { ... public static Size convertIntValue(int value) { if (value < SIZE_L || value > SIZE_S) { return null; } return new Size(value); } }


saveSize()経由でしか保存しないようにするなら、厳密にチェックしてなくてもいいのかなという気はしますが。


0 件のコメント:

コメントを投稿