SharedPreferences保存List和对象序列化数据

    xiaoxiao2021-03-25  98

            在Android下做持久化的数据存储,大部分是用到了sqlite数据库或者sharepreference。为了少写sql语句,大部分都是用ORM形式的开源数据库框架,例如greendao和cupboard或者dao4,但是在一般小型存储系统中,我还是比较喜欢用sp来存储,毕竟使用方便,数据量又不大,存储些不是很多的对象数据,用sp来存储还是很方便的。主要有两种方法来存储对象。

           1.存储List类型的数据

           用于保存各种List数据,最常见的莫过于,ListView、Gridviw中的数据,支持类型有:

          (1)List<String>

          (2)List<Map<String,Object>>

          (3)List<JavaBean>

          处理的方式时用Gson把List转换成json类型,再利用SharedPreferences保存的。

          处理工具类如下:

        

    public class ListDataSave { private SharedPreferences preferences; private SharedPreferences.Editor editor; public ListDataSave(Context mContext, String preferenceName) { preferences = mContext.getSharedPreferences(preferenceName, Context.MODE_PRIVATE); editor = preferences.edit(); } /** * 保存List * @param tag * @param datalist */ public <T> void setDataList(String tag, List<T> datalist) { if (null == datalist || datalist.size() <= 0) return; Gson gson = new Gson(); //转换成json数据,再保存 String strJson = gson.toJson(datalist); editor.clear(); editor.putString(tag, strJson); editor.commit(); } /** * 获取List * @param tag * @return */ public <T> List<T> getDataList(String tag) { List<T> datalist=new ArrayList<T>(); String strJson = preferences.getString(tag, null); if (null == strJson) { return datalist; } Gson gson = new Gson(); datalist = gson.fromJson(strJson, new TypeToken<List<T>>() { }.getType()); return datalist; } }   Userbean类如下:

    public class Userbean { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } MainActivity类:

    public class MainActivity extends Activity implements OnClickListener { Context mContext; ListDataSave dataSave; private ArrayList<Userbean> listBean; private ArrayList<String> listString; private ArrayList<Map<String, Object>> listMap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initView(); } private void initView() { findViewById(R.id.btn_addString).setOnClickListener(this); findViewById(R.id.btn_addJavaBean).setOnClickListener(this); findViewById(R.id.btn_addMap).setOnClickListener(this); findViewById(R.id.btn_getString).setOnClickListener(this); findViewById(R.id.btn_getJavaBean).setOnClickListener(this); findViewById(R.id.btn_getMap).setOnClickListener(this); mContext = getApplicationContext(); dataSave = new ListDataSave(mContext, "baiyu"); listString = new ArrayList<String>(); listBean = new ArrayList<Userbean>(); listMap = new ArrayList<Map<String, Object>>(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_addString: String s = "小名"; listString.add(s); dataSave.setDataList("string", listString); break; case R.id.btn_getString: Toast.makeText(mContext, dataSave.getDataList("string").toString(), Toast.LENGTH_SHORT).show(); break; case R.id.btn_addJavaBean: Userbean user = new Userbean(); user.setName("小白"); user.setAge(16); listBean.add(user); dataSave.setDataList("javaBean", listBean); break; case R.id.btn_getJavaBean: Toast.makeText(mContext, dataSave.getDataList("javaBean").toString(), Toast.LENGTH_SHORT).show(); break; case R.id.btn_addMap: Map<String, Object> map=new HashMap<String, Object>(); map.put("name","大白"); map.put("age", 18); listMap.add(map); dataSave.setDataList("listMap", listMap); break; case R.id.btn_getMap: Toast.makeText(mContext, dataSave.getDataList("listMap").toString(), Toast.LENGTH_SHORT).show(); break; } } } 2.存储序列化对象

    sharepreference存储对象是利用将对象转化为字节流,然后写入本地xml文件中,下次通过读取设置时的id来实现从xml文件中读取字节流然后再转化为对象

    保存对象的工具类:

    import android.content.Context; import android.content.SharedPreferences; import android.util.Base64; import android.util.Log; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.StreamCorruptedException; public class SaveObjectUtils { private Context context; private String name; public SaveObjectUtils(Context context, String name) { this.context = context; this.name = name; } /** * 根据key和预期的value类型获取value的值 * * @param key * @param clazz * @return */ public <T> T getValue(String key, Class<T> clazz) { if (context == null) { throw new RuntimeException("请先调用带有context,name参数的构造!"); } SharedPreferences sp = this.context.getSharedPreferences(this.name, Context.MODE_PRIVATE); return getValue(key, clazz, sp); } /** * 针对复杂类型存储<对象> * * @param key * @param object */ public void setObject(String key, Object object) { SharedPreferences sp = this.context.getSharedPreferences(this.name, Context.MODE_PRIVATE); //创建字节输出流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建字节对象输出流 ObjectOutputStream out = null; try { //然后通过将字对象进行64转码,写入key值为key的sp中 out = new ObjectOutputStream(baos); out.writeObject(object); String objectVal = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT)); SharedPreferences.Editor editor = sp.edit(); editor.putString(key, objectVal); editor.commit(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (baos != null) { baos.close(); } if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } } @SuppressWarnings("unchecked") public <T> T getObject(String key, Class<T> clazz) { SharedPreferences sp = this.context.getSharedPreferences(this.name, Context.MODE_PRIVATE); if (sp.contains(key)) { String objectVal = sp.getString(key, null); byte[] buffer = Base64.decode(objectVal, 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; } /** * 对于外部不可见的过渡方法 * * @param key * @param clazz * @param sp * @return */ @SuppressWarnings("unchecked") private <T> T getValue(String key, Class<T> clazz, SharedPreferences sp) { T t; try { t = clazz.newInstance(); 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)); } } catch (InstantiationException e) { e.printStackTrace(); Log.e("system", "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]"); } catch (IllegalAccessException e) { e.printStackTrace(); Log.e("system", "类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]"); } Log.e("system", "无法找到" + key + "对应的值"); return null; } } 单例的数据都封装在stateinfo实体 里面,点击储存时拿出对象存储,记得stateinfo一定要实现序列化接口,不然那会报空指针异常。

    import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.nickming.cachedemo.R; import com.nickming.cachedemo.db.MTStateInfo; import com.nickming.cachedemo.db.MTStateManager; import com.nickming.cachedemo.utils.SaveObjectUtils; public class Main2Activity extends AppCompatActivity { private Button mSave; private Button mShow; private TextView mResult; SaveObjectUtils utils; private static final String key=Main2Activity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); mSave= (Button) findViewById(R.id.btn_save1); mResult= (TextView) findViewById(R.id.tv_result1); mShow= (Button) findViewById(R.id.btn_show1); utils=new SaveObjectUtils(this,key); mSave.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MTStateManager.getInstance().setTaskId(324444); MTStateManager.getInstance().setBeginTime("20132003055"); MTStateInfo info=MTStateManager.getInstance().getStateInfo(); utils.setObject(""+info.getTaskId(),info); } }); mShow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MTStateInfo test=utils.getObject("324444",MTStateInfo.class); MTStateManager.getInstance().clearDatas(); MTStateManager.getInstance().setDatas(test); mResult.setText(""+MTStateManager.getInstance().getBeginTime()); } }); } } 用sp存储对象最大好处就是不要新建好多张表,例如我的stateinfo里还有一个自定义的对象,用greendao时还需要再声明一次,但是用sp就不需要,他不管你是自定义的还是系统的,都能毫无差错的存储

    转载请注明原文地址: https://ju.6miu.com/read-22651.html

    最新回复(0)