使用SharedPreferences儲存List
一次實際需求中需要把一個 list<String>
儲存到本地,那麼有其中一種操作就是使用 SharedPreferences
。這裡最後會給出泛型list儲存。
很顯然,檢視系統這個類提供的putXXX方法,並沒有發現能夠直接儲存list的。倒是發現有一個 StringSet
相關的。
只是看似可行方式 putStringSet(String key, Set<String> values);
那把list轉換為set儲存,這樣操作結果怎麼樣呢?
- set集合元素唯一,無序;list集合元素可以重複,有序。
- set轉list:資料保持不變,順序發生變化,可以使用Collections.sort進行排序(Collections.shuffle 隨機排序,Collections.reverse 反轉順序)。
- list轉set:去除重複資料,只保留一個。轉成linkedHashSet時,原順序不變;轉成treeSet可以排序,轉成hashSet無序。
既不能保證資料的順序,就算可以自定義排序規則,那也是相當麻煩的。而且資料也不能重複。所以放棄這種。還是選擇下面這種傳統一點好了。
推薦方式:把這個 List
序列化為 String
,然後使用 putString()
來儲存
直接貼一下程式碼
import android.content.Context; import android.content.SharedPreferences; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import com.example.AppContext; import java.lang.reflect.Type; import java.util.List; public class CommonSharedPrefs { private static final String STORE_FILE_NAME = "num_list_file"; private static SharedPreferences sharedPreferences = AppContext.getContext().getSharedPreferences(STORE_FILE_NAME, Context.MODE_PRIVATE); private static SharedPreferences.Editor editor = sharedPreferences.edit(); public static <T> void saveList(String key, List<T> list) { // 註釋1 Type personType = new TypeToken<List<T>>() { }.getType(); Gson gson = new Gson(); String json = gson.toJson(list, personType); set(key, json); } private static void set(String key, String value) { editor.putString(key, value); editor.commit(); } public static <T> List<T> getList(String key, Class<T> clazz) { List<T> list = null; try { String string = sharedPreferences.getString(key, null); Gson gson = new Gson(); //註釋2 Type type = new ParameterizedTypeImpl(List.class, new Class[]{clazz}); list = gson.fromJson(string, type); } catch (Exception e) { e.printStackTrace(); } return list; } }
上述程式碼的核心邏輯是,使用了Gson工具包來處理List與String之間轉換。需要注意以下三點:
-
如果你儲存的是其他bean,記得要把這個bean序列化,也就是泛型T要進行序列化
-
Gson是不支援序列化匿名型別的。
如下圖,為了省事,我直接使用匿名進行了初始化。那這個時候就需要手動為Gson指定型別,上圖註釋1處。
private List<String> numList = new ArrayList<String>() { { add("1"); add("2"); add("3"); add("4"); add("5"); add("6"); add("10"); add("11"); add("12"); } };
-
關於註釋2處 這裡要說明一下上面getList的泛型封裝
image.png
最開始我用的是上面這種方式來為這個List指定泛型,但是這種是無效的。那麼怎麼才能讓外部動態的來指定這個泛型呢?
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class ParameterizedTypeImpl implements ParameterizedType { private final Class raw; private final Type[] args; public ParameterizedTypeImpl(Class raw, Type[] args) { this.raw = raw; this.args = args != null ? args : new Type[0]; } @Override public Type[] getActualTypeArguments() { return args; } @Override public Type getRawType() { return raw; } @Override public Type getOwnerType() { return null; } }