2015年5月19日火曜日

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

前回 の続きです。


1. enum 版で SharedPreferences

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

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

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



2. class 版で SharedPreferences

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



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


0 件のコメント:

コメントを投稿