利用Gson和SharePreference存储结构化数据

具体的步骤

这个假设有三个User对象生成一个ArrayList<User>:

User user1 = new User("jack", "123456789", "http://www.hello.com/1.png");
User user2 = new User("tom", "45467956456", "http://www.hello.com/2.png");
User user3 = new User("lily", "65465897faf", "http://www.hello.com/3.png");
ArrayList<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);

利用Gson转化ArrayList<User>成Json Array数据:

Gson gson = new Gson();
String jsonStr = gson.toJson(users);
SPUtils.put(mContext, "USERS_KEY", jsonStr);

这里的jsonStr内容是:

[{"access_token":"123456789","profile_pic":"http://www.hello.com/1.png","username":"jack"},{"access_token":"45467956456","profile_pic":"http://www.hello.com/2.png","username":"tom"},{"access_token":"65465897faf","profile_pic":"http://www.hello.com/3.png","username":"lily"}]

这个时候看下sharepreference的xml文件里面有啥:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="USERS_KEY">[{&quot;access_token&quot;:&quot;123456789&quot;,&quot;profile_pic&quot;:&quot;http://www.hello.com/1.png&quot;,&quot;username&quot;:&quot;jack&quot;},{&quot;access_token&quot;:&quot;45467956456&quot;,&quot;profile_pic&quot;:&quot;http://www.hello.com/2.png&quot;,&quot;username&quot;:&quot;tom&quot;},{&quot;access_token&quot;:&quot;65465897faf&quot;,&quot;profile_pic&quot;:&quot;http://www.hello.com/3.png&quot;,&quot;username&quot;:&quot;lily&quot;}]</string>
</map>

发现String数据已经存储到了sharepreference中。那么该如何解析出来成bean对象呢?比如后面需要查jack这个人的对应的profile_pic:

String str = (String) SPUtils.get(mContext, "USERS_KEY", "");
users = gson.fromJson(str, new TypeToken<List<User>>() {}.getType());
for (User user : users) {
if (user.getUsername().equals("jack")) {
L.d(user.getProfile_pic());
}
}

在logcat中可以看到成功的打印出了Jack的profile_pic:

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAR8AAAAfCAIAAABRQl6uAAADYUlEQVR4nO2awXWDMAyGu42xMkEmyCk3JuCclwHoBgzCErmxB52lBwgBWxZgLEKb/3scUvSqGFm/bDl8nQAAOny9ewAA/FugLgC0gLoA0ALqAkALqAsALVKqyxatKW4JHW6H6Grvrcmvq0zaxAWKLnX2/dNfF1poOiBvjPzO7KcuutSmrC0xcy+YNvKWL51lSxkiumVly0pIMB0KNvKUN9n3z9Gq80b+ubpsEayRgkmbD1eXE/lu2CavsvJwe5+NvNT1eDwej8cWX0dTF50rUzb2zH1j2LQDn6wuP/K2aLML9RqDukJ0SdMt8dn3j7lXRHR6LvrO1VUvwXR6FjlbtP39wHYilE+UN6HZckyUN8No/ceJMMUFqh/MqInyXUWoaxxkf8Ahuu7In5SQQzpXpqxtt8G7V91TsFPGxmetuoTckNOGSTm1epR4ZzgkxHO5H03J+rVr6vBq7270BXWtykJ/AEPnHWfiA8Q/1yRQlDeDT/6RV6rLFq3rcIHAhFwPOaRzZcrW3KvXBz/Oc4Nfpa5QbiwNb1fFNJd6xb7L+TNOXQs9LPfJmvq626dIY8805EGcSR5bKFC+ODkBr6ka58owd+a3xOyyLDucfnht9uQq5gx+3doVyA0hD8efdzi6VOy7dNS1qFlaexBPdMu6zMibrKhNfn3diTLJwwur65aVrbNv2ayuyXji9L/E4ay65GxOoa5+YEIevm3t+iPqWrR2rT3P6HuMy9Xea0u3rN/e1JYoziQPb0Zd4nzvs3bZgt9Ablm75K/eZ+1ymy7lE6Add4bexMyapuu428idwn2XcLQQMtmiNUXdmWzRZkU9pFecaXDrHAnIgRoXV5YEfdf08dkR9r0Tt86EHM6qa+ZIWez05Bg6uSFvvPc8U91PXSfnrInViXdmKFcaVl1xZ9ZjV/15l1PwVprGj+DflMrQtL46zfpak2P105cd4Wkoedx8sQ5ldc1Hfjx4tkJxgWVzQype45daAgFJyKHfM4x8YyjQkcsmoEryyEfkxpKdc1qSqcv/2Wr7ZcrWeF3+kn9h/0sw4VK9NCKfJDfGd1IJYcw/XLvAJ5DgTWjux+60HFpdAPxpoC4AtIC6ANAC6gJAC6gLAC2gLgC0gLoA0ALqAkALqAsALaAuALSAugDQ4heI8p7EFwHmyAAAAABJRU5ErkJggg==" alt="" />

如果需要存储的数据比较多,可以将每个Bean对象抽取出一个key(比如username)形成一个key的ArrayList,同时将这个key的ArrayList存储到SharePreferecene,方便后续取出bean对象。

方法23:存对象 (sharedPreferences+base64)

注意:
(1)这里的object必须implement Serializable这个接口。
(2)本质上这里使用的是String来存储对象,只是先将对象序列化为String了。

/**
* 将对象进行base64编码后保存到SharePref中
* @param key
* @param object
*/
public static void saveObj(Context context, String key, Object object) {
if (sp == null)
sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
// 将对象的转为base64码
String objBase64 = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));
sp.edit().putString(key, objBase64).commit();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 将SharePref中经过base64编码的对象读取出来
* @param key
* @param defValue
*/
public static Object getObj(Context context, String key) {
if (sp == null)
sp = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
String objBase64 = sp.getString(key, null);
if (TextUtils.isEmpty(objBase64))
return null;
// 对Base64格式的字符串进行解码
byte[] base64Bytes = Base64.decode(objBase64.getBytes(), Base64.DEFAULT);
ByteArrayInputStream bais = new ByteArrayInputStream(base64Bytes);
ObjectInputStream ois;
Object obj = null;
try {
ois = new ObjectInputStream(bais);
obj = (Object) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}

方法22:保存List(Map(String, String)),(SharedPreferences+JsonArray )

原因:
SharedPreferences没有保存数组的方法,但是有时候为了保存一个数组而进行序列化,或者 动用sqlite都是有点杀猪焉用牛刀的感觉,所以就自己动手改进一下吧。

解决方案:方式是先转换成JSON,然后保存字符串,取出的时候再讲JSON转换成数组就好了。

public void saveInfo(Context context, String key, List<Map<String, String>> datas) {
JSONArray mJsonArray = new JSONArray();
for (int i = 0; i < datas.size(); i++) {
Map<String, String> itemMap = datas.get(i);
Iterator<Entry<String, String>> iterator = itemMap.entrySet().iterator();
JSONObject object = new JSONObject();

while (iterator.hasNext()) {
Entry<String, String> entry = iterator.next();
try {
object.put(entry.getKey(), entry.getValue());
} catch (JSONException e) {

}
}
mJsonArray.put(object);
}

SharedPreferences sp = context.getSharedPreferences("finals", Context.MODE_PRIVATE);
Editor editor = sp.edit();
editor.putString(key, mJsonArray.toString());
editor.commit();
}

public List<Map<String, String>> getInfo(Context context, String key) {
List<Map<String, String>> datas = new ArrayList<Map<String, String>>();
SharedPreferences sp = context.getSharedPreferences("finals", Context.MODE_PRIVATE);
String result = sp.getString(key, "");
try {
JSONArray array = new JSONArray(result);
for (int i = 0; i < array.length(); i++) {
JSONObject itemObject = array.getJSONObject(i);
Map<String, String> itemMap = new HashMap<String, String>();
JSONArray names = itemObject.names();
if (names != null) {
for (int j = 0; j < names.length(); j++) {
String name = names.getString(j);
String value = itemObject.getString(name);
itemMap.put(name, value);
}
}
datas.add(itemMap);
}
} catch (JSONException e) {
}
return datas;
}

方法21:保存Object或者ListObject (sharedPreferences+json)

Sharepreference是Android常用的数据存储技术,以key-value保存在手机本地,经常只是用来保存基本类型数据,
Google也只是提供putLong(),putBoolean(),putString()…实际项目中,我们经常是需要缓存Object或者ListObject,方便我们对App逻辑的操作,这时候我们就需要进一步封装,
利用Gson把Object或者ListObject转成String,用putString()保存,需要展示缓存内容时,get到String,利用Gson转成Object或者ListObject.
实际项目开发中,建议对Sharedpreference做成工具类,代码会简洁,直观。

存储Object对象

public void saveObject(String key, Object obj) {
SharedPreferences.Editor edit = settings.edit();
String str = gson.toJson(obj, obj.getClass());
edit.putString(key, str);
edit.commit();
}

获取存储Object对象

public <T> T getObject(String key, Class<?> classItem) {
try {
String str = settings.getString(key, null);
if (str != null) {
return (T) gson.fromJson(str, classItem);
}
} catch (Exception e) {

}

存储ListObeject对象
public <T> void saveListObject(String key, List<T> list) {
SharedPreferences.Editor edit = settings.edit();
String str = gson.toJson(list);
edit.putString(key, str);
edit.commit();
}
}

获取ListObeject对象
public List getListObject(String key,Class<?> classItem) {
JavaType javaType = mapper.getTypeFactory().constructCollectionType(ArrayList.class, classItem);
try {
String str = settings.getString(key, null);
if (str != null) {
return mapper.readValue(str,javaType);
}
} catch (Exception e) {

}
return null;
}

以上是我在实际开发中,Sharedpreference 对Object和ListObject封装,欢迎交流指正。

方法2: 保存list( Json+SharedPrefernces ):

先把PlayList对象转换为JSON形式的字符串,用SharedPreferences来保存字符串。
/**
* 把播放列表转换为JSON形式以字符串形式保存
* @param object 播放列表对象
*/
public static void getJsonStringByEntity(Context context, Object object) {
String strJson = "";
Gson gson = new Gson();
strJson = gson.toJson(object);
saveSharePlayList(context,strJson);
}

读取出来的:
/**
* 读取播放列表数据
*/
public static PlayList getfromJson(Context context){
PlayList list = null;
String str = readSharePlayList(context);
if(str!=null){
Gson gson=new Gson();
list = gson.fromJson(str, new TypeToken<PlayList>(){}.getType());
}
return list;
}

方法1:依赖包:

直接转成String后再转回来降低了效率,这里有一个存储简单对象的编译时注解库:
https://github.com/2tu/fit 。
Fit 使用SharedPreferences存储对象中的基本数据类型。利用APT编译时生成代码,与转成String及反射相比更快。
支持:基本类型,基本包装类型,Set,minSDK 11。

SharePrecences--(json+sharePrecences)存list 或对象的更多相关文章

  1. ios 把数组对象转成json字符串存起来

    1第一步是我们获取数据源 一般我们都是从接口请求数据 NSArray *subColumnsArray = nil; NSDictionary *dict = [NSJSONSerialization ...

  2. json 串转成 java 对象再拼接成前台 html 元素

    获取商品参数 json 串,转成 java 对象,再拼接成前台 html 的Service方法 @Override public String getItemParam(Long itemId) { ...

  3. [MVC_Json序列化]Json字符串反序列化成C#对象

    上一篇中有Json序列化相关问题得到了解决. 那么结果集为Json串时,如何将Json串转成C#对象呢? 现举例说明: -现有如下字符串数据 string k = "{\"ring ...

  4. js中json字符串转成js对象

    json字符串转成js对象我所知的方法有2种: //json字符串转换成json对象 var str_json = "{name:'liuchuan'}"; //json字符串 / ...

  5. .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二)

    .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一) 上一篇主 ...

  6. .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (一)

    .net core 1.1.0 MVC 控制器接收Json字串 (JObject对象) (二) Json是WEB交互常见的数据,.net core 处理方式是转为强类型,没有对应的强类型会被抛弃,有时 ...

  7. 类对象序列化为json串,json串反序列化为类对象

    1.类对象序列化为json串: 方法一: class P(object): def __init__(self,name,age,sex): self.name=name self.age=age s ...

  8. EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象

    EF+LINQ事物处理   在使用EF的情况下,怎么进行事务的处理,来减少数据操作时的失误,比如重复插入数据等等这些问题,这都是经常会遇到的一些问题 但是如果是我有多个站点,然后存在同类型的角色去操作 ...

  9. python 将一个JSON 字典转换为一个Python 对象

    将一个JSON 字典转换为一个Python 对象例子 >>> s='{"name":"apple","shares":50 ...

  10. JSON(JavaScript Object Notation, JS 对象标记)

    JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式.它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言 ...

随机推荐

  1. [GodLove]Wine93 Tarining Round #4

    比赛链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=44903#overview 题目来源: 2011 Asia ChengDu R ...

  2. Eclipse的FindBugs插件

      Eclipse的FindBugs插件     问题提出: 当我们编写完代码,做完单元测试等各种测试后就提交正式运行,只能由运行的系统来检测我们代码是否有问题了,代码中隐藏的错误在系统运行的过程中被 ...

  3. system占用80端口的问题

    80端口被占用的问题 首先可以看看是不是iis占用了.如果是的话.修改为其他端口即可. 如果不是.. 在cmd中输入命令netstat -ano 查看是不是system占用了80端口? 如果是syst ...

  4. java程序链接到sql server数据库

    package jianhua; import java.sql.*; public class ConDatabase { public static void main(String[] args ...

  5. 关于java中static的应用及一种常见错误

    JAVA中的static的应用 在web项目的开发中,遇到了类中的static方法不奏效. 在开发过程中,我定义了一个静态方法初始化数组,但是在创建类的对象后,访问该数组是全为null.我一直以为st ...

  6. CSS应用心得

    单纯Html配合CSS网页 下面用程序来实际总结一下 首先,在写程序的应该具有一个良好的编程习惯. 第一:排版,拥有一个良好的排版,有助于我们能够快速的理解以及阅读程序: 第二:注释,就如以下程序,作 ...

  7. dependency of static library

    一直以来都有一个误区,认为静态库就一定是不含任何依赖的,动态库是含的.这个印象是因为在我们程序中,包含静态库的地方,往往Build好之后直接就可以用,而含DLL的地方,则需要在build好之后的EXE ...

  8. dict

    1.创建新字典(根据语法和dict初始化方法) >>> my_dict={'a':1,'b':2,'c':3} >>> my_dict=dict({'a':1,'b ...

  9. HTTP Code

    所有 HTTP 状态代码及其定义. 代码  指示  2xx  成功  200  正常:请求已完成.  201  正常:紧接 POST 命令.  202  正常:已接受用于处理,但处理尚未完成.  20 ...

  10. Object.create() 和 __proto__ 的关系

    经测试得出 Ojbect.create() 也就是通过修改 __proto__ 实现的. 例: var Super = { say: function() {console.log('say')} } ...