Android提供了五种数据存储方式:
在 Android 下做持久化的数据存储,大部分是用 sqlite 数据库或 sharepreference。为了少写 sql 语句,大部分都是用 ORM 形式的开源数据库框架,例如 greendao 和 cupboard 或者 dao4,但在一般小型存储系统中,还是用 sharepreference 存储比较方便。
SharedPreferences 是 Android 平台上一个轻量级的存储辅助类,用来保存应用的一些常用配置。
SharedPreferences 可存储的数据类型有:
最终数据是以xml形式进行存储。
SharedPreferences 文件都是存放在 /data/data//shared_prefs/目录下的,在模拟器上可以看见该文件;在真机上,需要对真机root后,才能看到该文件。
下面总结 SharedPreferences 可存储的数据类型。
SharedPreferences 可存储四种基本类型数据(int,float,long,boolean)+ String。
SPUtil
/**
* 获取SharedPreference保存的value
* 值的类型:(int,float,long,boolean)+String
*
* @param context 上下文
* @param key 储存值的key
* @param clazz 获取值的类型 int,float,long,boolean)+String
* @param T
* @return 值
*/
public static T getValue(Context context, String key, Class clazz) {
if (context == null) {
throw new RuntimeException("context is null");
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
return getValue(key, getT(clazz), sp);
}
/**
* 获取SharedPreference保存的value
* 值的类型:(int,float,long,boolean)+String
*
* @param key 储存值的key
* @param T 获取值的类型 int,float,long,boolean)+String
* @param sp SharedPreferences
* @param T
* @return 值
*/
private static T getValue(String key, T t, SharedPreferences sp) {
if (t == null) {
return null;
}
if (t instanceof Integer) {
return (T) Integer.valueOf(sp.getInt(key, 0));
} else if (t instanceof String) {
return (T) sp.getString(key, "");
} else if (t instanceof Boolean) {
return (T) Boolean.valueOf(sp.getBoolean(key, false));
} else if (t instanceof Long) {
return (T) Long.valueOf(sp.getLong(key, 0L));
} else if (t instanceof Float) {
return (T) Float.valueOf(sp.getFloat(key, 0L));
}
Log.e(TAG, "无法找到" + key + "对应的值");
return null;
}
/**
* 通过反射创建类实例
* 反射有两种方式创建类实例:
* 1、Class.newInstance():只能调用无参的构造函数(默认构造函数)
* 2、Constructor.newInstance():可以根据传入的参数,调用任意构造构造函数。
* Integer、Boolean、Long、Float 没有默认构造函数,只能通过 Constructor.newInstance() 调用
* String 是有默认构造函数的,两种方法都适用
* @param clazz String.class、Integer.class、Boolean.class、Long.class、Float.class
* @param T
* @return T
*/
private static T getT(Class clazz) {
T t = null;
String clazzName = clazz.getName();
Log.e(TAG, "基本类型名字是[" + clazzName + "]");
try {
if ("java.lang.Integer".equals(clazzName)) {
t = clazz.getConstructor(int.class).newInstance(1);
} else if ("java.lang.String".equals(clazzName)) {
t = clazz.newInstance();
} else if ("java.lang.Boolean".equals(clazzName)) {
t = clazz.getConstructor(boolean.class).newInstance(false);
} else if ("java.lang.Long".equals(clazzName)) {
t = clazz.getConstructor(long.class).newInstance(0L);
} else if ("java.lang.Float".equals(clazzName)) {
t = clazz.getConstructor(float.class).newInstance(0F);
}
} catch (InstantiationException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
} catch (IllegalAccessException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
} catch (InvocationTargetException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
} catch (NoSuchMethodException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
}
return t;
}
/**
* 使用SharedPreference保存value
*
* @param context 上下文
* @param key 储存值的key
* @param value 值
*/
public static void setValue(Context context, String key, Object value) {
if (context == null) {
throw new RuntimeException("context is null");
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
setValue(key, value, sp);
}
/**
* 使用SharedPreference保存value
*
* @param key 储存值的key
* @param value 值
* @param sp SharedPreferences
*/
private static void setValue(String key, Object value, SharedPreferences sp) {
SharedPreferences.Editor editor = sp.edit();
if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
} else if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
} else if (value instanceof Long) {
editor.putLong(key, (Long) value);
} else if (value instanceof Float) {
editor.putFloat(key, (Float) value);
}
editor.commit();
}
注:
通过反射创建类实例
反射有两种方式创建类实例:
1、Class.newInstance():只能调用无参的构造函数(默认构造函数)
2、Constructor.newInstance():可以根据传入的参数,调用任意构造构造函数
Integer、Boolean、Long、Float 没有默认构造函数,只能通过 Constructor.newInstance() 调用
String 是有默认构造函数的,两种方法都适用
在 SPTestActivity 中使用
//存储
String str = etContent.getText().toString().trim();
if (TextUtils.isEmpty(str)) {
ToastUtils.toast(this, "请输入内容");
return;
}
// SPUtil.setValue(this, "base_value", str);
// SPUtil.setValue(this, "base_value_int", 2);
// SPUtil.setValue(this, "base_value_boolean", true);
// SPUtil.setValue(this, "base_value_long", 3L);
SPUtil.setValue(this, "base_value_float", 3.5F);
ToastUtils.toast(this, "数据保存成功!");
//读取
String value = SPUtil.getValue(this, "base_value", String.class);
// int value = SPUtil.getValue(this, "base_value_int", Integer.class);
// boolean value = SPUtil.getValue(this, "base_value_boolean", Boolean.class);
// long value = SPUtil.getValue(this, "base_value_long", Long.class);
float value = SPUtil.getValue(this, "base_value_float", Float.class);
ToastUtils.toast(this, String.valueOf(value));
SharedPreferences 存储对象是将对象转化为字节流,然后写入本地xml文件中; 读取时,从xml文件中读取字节流然后转化为对象。
存储对象流程:
SPUtil
/**
* 使用SharedPreference保存序列化对象
* 用Base64.encode将字节文件转换成Base64编码保存在String中
*
* @param context 上下文
* @param key 储存对象的key
* @param object object对象 对象必须实现Serializable序列化,否则会出问题,
* out.writeObject 无法写入 Parcelable 序列化的对象
*/
public static void setObject(Context context, String key, Object object) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
//创建字节输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//创建字节对象输出流
ObjectOutputStream out = null;
try {
//然后通过将字对象进行64转码,写入sp中
out = new ObjectOutputStream(baos);
out.writeObject(object);
String objectValue = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, objectValue);
editor.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取SharedPreference保存的对象
* 使用Base64解密String,返回Object对象
*
* @param context 上下文
* @param key 储存对象的key
* @param 泛型
* @return 返回保存的对象
*/
public static T getObject(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
if (sp.contains(key)) {
String objectValue = sp.getString(key, null);
byte[] buffer = Base64.decode(objectValue, Base64.DEFAULT);
//一样通过读取字节流,创建字节流输入流,写入对象并作强制转换
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bais);
T t = (T) ois.readObject();
return t;
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (bais != null) {
bais.close();
}
if (ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
在 SPTestActivity 中使用
//存储
UserModel userModel = new UserModel();
userModel.name = "张三";
userModel.age = 20;
SPUtil.setObject(this, "user_model", userModel);
ToastUtils.toast(this, "数据保存成功!");
//读取
UserModel user = SPUtil.getObject(this, "user_model");
ToastUtils.toast(this, "姓名:" + user.name + ",年龄:" + user.age);
UserModel 对象
public class UserModel implements Serializable {
public int id;
public String name;
public int age;
}
用于保存List数据,支持的类型有:
存储List类型的数据
/**
* 使用SharedPreferences保存List
* 支持类型:List,List
*
* @param context 上下文
* @param key 储存的key
* @param dataList 存储数据
* @param 泛型
*/
public static void setDataList(Context context, String key, List dataList) {
if (null == dataList || dataList.size() < 0) {
return;
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
Gson gson = new Gson();
//转换成json数据,再保存
String strJson = gson.toJson(dataList);
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, strJson);
editor.commit();
}
读取List类型的数据
/**
* 获取SharedPreferences保存的List
*
* @param context 上下文
* @param key 储存的key
* @param 泛型
* @return 存储List数据
*/
public static List getDataList(Context context, String key, Class cls) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
List dataList = new ArrayList();
String strJson = sp.getString(key, null);
if (null == strJson) {
return dataList;
}
Gson gson = new Gson();
//使用泛型解析数据会出错,返回的数据类型是LinkedTreeMap
dataList = gson.fromJson(strJson, new TypeToken>() {
}.getType());
return dataList;
}
在 SPTestActivity 中使用
//存储
List userList = new ArrayList<>();
for (int i = 0; i < 5; i ++) {
UserModel userModel1 = new UserModel();
userModel1.name = "名字:" + i;
userList.add(userModel1);
}
SPUtil.setDataList(this, "user_list", userList);
ToastUtils.toast(this, "数据保存成功!");
//读取
List dataList = SPUtil.getDataList(this, "user_list");
StringBuffer buffer = new StringBuffer();
for (UserModel user1 : dataList) {
buffer.append(user1.name + ";");
}
ToastUtils.toast(this, buffer.toString());
运行后,会发现,在读取数据的时候,会抛出异常:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.example.rs.recyclerviewdemo.model.UserModel
看错误信息,是 “类型” 转换问题。
断点调试下
用这种方式读取数据:
/**
* 获取SharedPreferences保存的List
*
* @param context 上下文
* @param key 储存的key
* @param 泛型
* @return 存储List数据
*/
public static List getDataList(Context context, String key, Class cls) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
List dataList = new ArrayList();
String strJson = sp.getString(key, null);
if (null == strJson) {
return dataList;
}
Gson gson = new Gson();
//使用泛型解析数据会出错,返回的数据类型是LinkedTreeMap
dataList = gson.fromJson(strJson, new TypeToken>() {
}.getType());
return dataList;
}
断点调试结果:
可看到,返回的类型是个LinkedTreeMap,所以当把解析后的集合遍历复制给 UserModel 的时候就会报 “类型” 转换错误的异常。
对从 SharedPreferences 读取数据那块代码进行改造:
public static List getDataList(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
List dataList = new ArrayList();
String strJson = sp.getString(key, null);
if (null == strJson) {
return dataList;
}
Gson gson = new Gson();
//使用泛型解析数据会出错,返回的数据类型是LinkedTreeMap
// dataList = gson.fromJson(strJson, new TypeToken>() {
// }.getType());
//这样写,太死
dataList = gson.fromJson(strJson, new TypeToken>() {
}.getType());
return dataList;
}
在解析时,将 T 泛型改为 UserModel 对象进行解析,再次运行,读取正常。
断点调试查看数据:
dataList 里存入的是 UserModel 对象,解析正常。
但是解析类型规定死,这样太死了,无法扩展。
再次进行改造:
/**
* 获取SharedPreferences保存的List
*
* @param context 上下文
* @param key 储存的key
* @param 泛型
* @return 存储List数据
*/
public static List getDataList(Context context, String key, Class cls) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
List dataList = new ArrayList();
String strJson = sp.getString(key, null);
if (null == strJson) {
return dataList;
}
Gson gson = new Gson();
//使用泛型解析数据会出错,返回的数据类型是LinkedTreeMap
// dataList = gson.fromJson(strJson, new TypeToken>() {
// }.getType());
//这样写,太死
// dataList = gson.fromJson(strJson, new TypeToken>() {
// }.getType());
JsonArray arry = new JsonParser().parse(strJson).getAsJsonArray();
for (JsonElement jsonElement : arry) {
dataList.add(gson.fromJson(jsonElement, cls));
}
return dataList;
}
调用:
List dataList = SPUtil.getDataList(this, "user_list",
UserModel.class);
StringBuffer buffer = new StringBuffer();
for (UserModel user1 : dataList) {
buffer.append(user1.name + ";");
}
ToastUtils.toast(this, buffer.toString());
OK ! ! !
或者参考LinkedTreeMap的处理方法
SharedPreferences 存储 Map
/**
* 使用SharedPreferences保存集合
* @param context 上下文
* @param key 储存的key
* @param map map数据
*/
public static void setHashMapData(Context context, String key, Map map){
if (map == null) {
return ;
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
Gson gson = new Gson();
String strJson = gson.toJson(map);
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, strJson);
editor.commit();
}
/**
* 获取SharedPreferences保存的集合
* @param context 上下文
* @param key 储存的key
* @param clsV 解析类型
* @return Map集合
*/
public static Map getHashMapData(Context context, String key, Class clsV){
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
Map map = new HashMap<>();
String strJson = sp.getString(key, "");
Gson gson = new Gson();
JsonObject obj =new JsonParser().parse(strJson).getAsJsonObject();
Set> entrySet = obj.entrySet();
for (Map.Entry entry : entrySet) {
String entryKey = entry.getKey();
JsonObject value = (JsonObject) entry.getValue();
map.put(entryKey, gson.fromJson(value, clsV));
}
return map;
}
使用:
//存储
Map map = new HashMap<>();
for (int i = 0; i < 5; i++) {
UserModel userModel1 = new UserModel();
userModel1.name = "姓名:" + i;
map.put(i +"", userModel1);
}
SPUtil.setHashMapData(this, "user_map", map);
ToastUtils.toast(this, "数据保存成功!");
//读取
Map userMap = SPUtil.getHashMapData(this, "user_map", UserModel.class);
UserModel userModel1 = userMap.get("1");
ToastUtils.toast(this, userModel1.name);
SPUtil
package com.example.rs.recyclerviewdemo.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Base64;
import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Created by sgll on 2019/1/15.
* SharedPreferences工具类
* 保存的数据类型有:
* 1、四种基本类型数据(int,float,long,boolean)+ String
* 2、List类型的数据
* 3、存储序列化对象
* 4、存储Map集合
*/
public class SPUtil {
private static String SP_NAME = "recyclerviewdemo_sp";
private static String TAG = "SharedPreferenceUtil";
/**
* 获取SharedPreference保存的value
* 值的类型:(int,float,long,boolean)+String
*
* @param context 上下文
* @param key 储存值的key
* @param clazz 获取值的类型 int,float,long,boolean)+String
* @param T
* @return 值
*/
public static T getValue(Context context, String key, Class clazz) {
if (context == null) {
throw new RuntimeException("context is null");
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
return getValue(key, getT(clazz), sp);
}
/**
* 获取SharedPreference保存的value
* 值的类型:(int,float,long,boolean)+String
*
* @param key 储存值的key
* @param T 获取值的类型 int,float,long,boolean)+String
* @param sp SharedPreferences
* @param T
* @return 值
*/
private static T getValue(String key, T t, SharedPreferences sp) {
if (t == null) {
return null;
}
if (t instanceof Integer) {
return (T) Integer.valueOf(sp.getInt(key, 0));
} else if (t instanceof String) {
return (T) sp.getString(key, "");
} else if (t instanceof Boolean) {
return (T) Boolean.valueOf(sp.getBoolean(key, false));
} else if (t instanceof Long) {
return (T) Long.valueOf(sp.getLong(key, 0L));
} else if (t instanceof Float) {
return (T) Float.valueOf(sp.getFloat(key, 0L));
}
Log.e(TAG, "无法找到" + key + "对应的值");
return null;
}
/**
* 通过反射创建类实例
* 反射有两种方式创建类实例:
* 1、Class.newInstance():只能调用无参的构造函数(默认构造函数)
* 2、Constructor.newInstance():可以根据传入的参数,调用任意构造构造函数。
* Integer、Boolean、Long、Float 没有默认构造函数,只能通过 Constructor.newInstance() 调用
* String 是有默认构造函数的,两种方法都适用
* @param clazz String.class、Integer.class、Boolean.class、Long.class、Float.class
* @param T
* @return T
*/
private static T getT(Class clazz) {
T t = null;
String clazzName = clazz.getName();
Log.e(TAG, "基本类型名字是[" + clazzName + "]");
try {
if ("java.lang.Integer".equals(clazzName)) {
t = clazz.getConstructor(int.class).newInstance(1);
} else if ("java.lang.String".equals(clazzName)) {
t = clazz.newInstance();
} else if ("java.lang.Boolean".equals(clazzName)) {
t = clazz.getConstructor(boolean.class).newInstance(false);
} else if ("java.lang.Long".equals(clazzName)) {
t = clazz.getConstructor(long.class).newInstance(0L);
} else if ("java.lang.Float".equals(clazzName)) {
t = clazz.getConstructor(float.class).newInstance(0F);
}
} catch (InstantiationException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
} catch (IllegalAccessException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
} catch (InvocationTargetException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
} catch (NoSuchMethodException e) {
Log.e(TAG, "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");
e.printStackTrace();
}
return t;
}
/**
* 使用SharedPreference保存value
*
* @param context 上下文
* @param key 储存值的key
* @param value 值
*/
public static void setValue(Context context, String key, Object value) {
if (context == null) {
throw new RuntimeException("context is null");
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
setValue(key, value, sp);
}
/**
* 使用SharedPreference保存value
*
* @param key 储存值的key
* @param value 值
* @param sp SharedPreferences
*/
private static void setValue(String key, Object value, SharedPreferences sp) {
SharedPreferences.Editor editor = sp.edit();
if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
} else if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
} else if (value instanceof Long) {
editor.putLong(key, (Long) value);
} else if (value instanceof Float) {
editor.putFloat(key, (Float) value);
}
editor.commit();
}
/**
* 使用SharedPreference保存序列化对象
* 用Base64.encode将字节文件转换成Base64编码保存在String中
*
* @param context 上下文
* @param key 储存对象的key
* @param object object对象 对象必须实现Serializable序列化,否则会出问题,
* out.writeObject 无法写入 Parcelable 序列化的对象
*/
public static void setObject(Context context, String key, Object object) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
//创建字节输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//创建字节对象输出流
ObjectOutputStream out = null;
try {
//然后通过将字对象进行64转码,写入sp中
out = new ObjectOutputStream(baos);
out.writeObject(object);
String objectValue = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, objectValue);
editor.commit();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (baos != null) {
baos.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取SharedPreference保存的对象
* 使用Base64解密String,返回Object对象
*
* @param context 上下文
* @param key 储存对象的key
* @param 泛型
* @return 返回保存的对象
*/
public static T getObject(Context context, String key) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
if (sp.contains(key)) {
String objectValue = sp.getString(key, null);
byte[] buffer = Base64.decode(objectValue, Base64.DEFAULT);
//一样通过读取字节流,创建字节流输入流,写入对象并作强制转换
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(bais);
T t = (T) ois.readObject();
return t;
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (bais != null) {
bais.close();
}
if (ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
/**
* 使用SharedPreferences保存List
* 支持类型:List,List
*
* @param context 上下文
* @param key 储存的key
* @param dataList 存储数据
* @param 泛型
*/
public static void setDataList(Context context, String key, List dataList) {
if (null == dataList || dataList.size() < 0) {
return;
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
Gson gson = new Gson();
//转换成json数据,再保存
String strJson = gson.toJson(dataList);
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, strJson);
editor.commit();
}
/**
* 获取SharedPreferences保存的List
*
* @param context 上下文
* @param key 储存的key
* @param 泛型
* @return 存储List数据
*/
public static List getDataList(Context context, String key, Class cls) {
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
List dataList = new ArrayList();
String strJson = sp.getString(key, null);
if (null == strJson) {
return dataList;
}
Gson gson = new Gson();
//使用泛型解析数据会出错,返回的数据类型是LinkedTreeMap
// dataList = gson.fromJson(strJson, new TypeToken>() {
// }.getType());
//这样写,太死
// dataList = gson.fromJson(strJson, new TypeToken>() {
// }.getType());
JsonArray arry = new JsonParser().parse(strJson).getAsJsonArray();
for (JsonElement jsonElement : arry) {
dataList.add(gson.fromJson(jsonElement, cls));
}
return dataList;
}
/**
* 使用SharedPreferences保存集合
* @param context 上下文
* @param key 储存的key
* @param map map数据
*/
public static void setHashMapData(Context context, String key, Map map){
if (map == null) {
return ;
}
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
Gson gson = new Gson();
String strJson = gson.toJson(map);
SharedPreferences.Editor editor = sp.edit();
editor.putString(key, strJson);
editor.commit();
}
/**
* 获取SharedPreferences保存的集合
* @param context 上下文
* @param key 储存的key
* @param clsV 解析类型
* @return Map集合
*/
public static Map getHashMapData(Context context, String key, Class clsV){
SharedPreferences sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
Map map = new HashMap<>();
String strJson = sp.getString(key, "");
Gson gson = new Gson();
JsonObject obj =new JsonParser().parse(strJson).getAsJsonObject();
Set> entrySet = obj.entrySet();
for (Map.Entry entry : entrySet) {
String entryKey = entry.getKey();
JsonObject value = (JsonObject) entry.getValue();
map.put(entryKey, gson.fromJson(value, clsV));
}
return map;
}
}
使用
package com.example.rs.recyclerviewdemo.activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import com.example.rs.recyclerviewdemo.R;
import com.example.rs.recyclerviewdemo.model.UserModel;
import com.example.rs.recyclerviewdemo.util.SPUtil;
import com.example.rs.recyclerviewdemo.util.ToastUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by sgll on 2019/1/15.
*/
public class SPTestActivity extends AppCompatActivity {
@BindView(R.id.et_content)
EditText etContent;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sp_test);
ButterKnife.bind(this);
}
@OnClick({R.id.bt_set_base, R.id.bt_get_base, R.id.bt_set_object, R.id.bt_get_object,
R.id.bt_set_list, R.id.bt_get_list, R.id.bt_set_map, R.id.bt_get_map})
void onClick(View view){
int viewId = view.getId();
switch (viewId) {
case R.id.bt_set_base:
String str = etContent.getText().toString().trim();
if (TextUtils.isEmpty(str)) {
ToastUtils.toast(this, "请输入内容");
return;
}
// SPUtil.setValue(this, "base_value", str);
// SPUtil.setValue(this, "base_value_int", 2);
// SPUtil.setValue(this, "base_value_boolean", true);
// SPUtil.setValue(this, "base_value_long", 3L);
SPUtil.setValue(this, "base_value_float", 3.5F);
ToastUtils.toast(this, "数据保存成功!");
break;
case R.id.bt_get_base:
// String value = SPUtil.getValue(this, "base_value", String.class);
// int value = SPUtil.getValue(this, "base_value_int", Integer.class);
// boolean value = SPUtil.getValue(this, "base_value_boolean", Boolean.class);
// long value = SPUtil.getValue(this, "base_value_long", Long.class);
float value = SPUtil.getValue(this, "base_value_float", Float.class);
ToastUtils.toast(this, String.valueOf(value));
break;
case R.id.bt_set_object:
UserModel userModel = new UserModel();
userModel.name = "张三";
userModel.age = 20;
SPUtil.setObject(this, "user_model", userModel);
ToastUtils.toast(this, "数据保存成功!");
break;
case R.id.bt_get_object:
UserModel user = SPUtil.getObject(this, "user_model");
ToastUtils.toast(this, "姓名:" + user.name + ",年龄:" + user.age);
break;
case R.id.bt_set_list:
List userList = new ArrayList<>();
for (int i = 0; i < 5; i ++) {
UserModel userModel1 = new UserModel();
userModel1.name = "名字:" + i;
userList.add(userModel1);
}
// List userList = new ArrayList<>();
// for (int i = 0; i < 5; i ++) {
// userList.add("你好:" + i);
// }
// List userList = new ArrayList<>();
// for (int i = 0; i < 5; i ++) {
// userList.add(i);
// }
SPUtil.setDataList(this, "user_list", userList);
ToastUtils.toast(this, "数据保存成功!");
break;
case R.id.bt_get_list:
List dataList = SPUtil.getDataList(this, "user_list",
UserModel.class);
StringBuffer buffer = new StringBuffer();
for (UserModel user1 : dataList) {
buffer.append(user1.name + ";");
}
// List dataList = SPUtil.getDataList(this, "user_list", String.class);
// for (String stra : dataList) {
// buffer.append(stra + ";");
// }
// List dataList = SPUtil.getDataList(this, "user_list", Integer.class);
// for (Integer stra : dataList) {
// buffer.append(stra + ";");
// }
ToastUtils.toast(this, buffer.toString());
break;
case R.id.bt_set_map:
Map map = new HashMap<>();
for (int i = 0; i < 5; i++) {
UserModel userModel1 = new UserModel();
userModel1.name = "姓名:" + i;
map.put(i +"", userModel1);
}
SPUtil.setHashMapData(this, "user_map", map);
ToastUtils.toast(this, "数据保存成功!");
break;
case R.id.bt_get_map:
Map userMap = SPUtil.getHashMapData(this, "user_map",
UserModel.class);
UserModel userModel1 = userMap.get("1");
ToastUtils.toast(this, userModel1.name);
break;
default:
break;
}
}
}
xml
UserModel
package com.example.rs.recyclerviewdemo.model;
import java.io.Serializable;
/**
* Created by sgll on 2019/1/16.
*/
public class UserModel implements Serializable {
public int id;
public String name;
public int age;
}
SharedPreference s是无法直接保存 Object,List 集合和 Map 集合的,需要先将它们转换为字符串,再保存到 SharedPreferences 中,取的时候再把对应的字符串转为 Object,List 集合或者 Map 集合。