Android下利用SharePreference存储序列化对象的方法

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

虽说sharepreference是轻量级存储工具,但他的功能还是很强大的,毕竟基于文件存储,虽说效率可能没有sql那么高,但是毕竟不要建立多张表,又不用写多个实体,把数据统统放在一个类里面,然后存储读取都能很方便的操作。

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

下面介绍一下关于利用sharepreference存储的用法:

[java]  view plain  copy
  1. package com.nickming.cachedemo.utils;  
  2.   
  3. import android.content.Context;  
  4. import android.content.SharedPreferences;  
  5. import android.util.Base64;  
  6. import android.util.Log;  
  7.   
  8. import java.io.ByteArrayInputStream;  
  9. import java.io.ByteArrayOutputStream;  
  10. import java.io.IOException;  
  11. import java.io.ObjectInputStream;  
  12. import java.io.ObjectOutputStream;  
  13. import java.io.StreamCorruptedException;  
  14.   
  15. /** 
  16.  * desc: 
  17.  * 
  18.  * @author:nickming date:2015/12/18 
  19.  * time: 01:10 
  20.  * e-mail:[email protected] 
  21.  */  
  22.   
  23. public class SaveObjectUtils {  
  24.   
  25.     private Context context;  
  26.     private String name;  
  27.   
  28.     public SaveObjectUtils(Context context, String name) {  
  29.         this.context = context;  
  30.         this.name = name;  
  31.     }  
  32.   
  33.     /** 
  34.      * 根据key和预期的value类型获取value的值 
  35.      * 
  36.      * @param key 
  37.      * @param clazz 
  38.      * @return 
  39.      */  
  40.     public  T getValue(String key, Class clazz) {  
  41.         if (context == null) {  
  42.             throw new RuntimeException("请先调用带有context,name参数的构造!");  
  43.         }  
  44.         SharedPreferences sp = this.context.getSharedPreferences(this.name, Context.MODE_PRIVATE);  
  45.         return getValue(key, clazz, sp);  
  46.     }  
  47.   
  48.     /** 
  49.      * 针对复杂类型存储<对象> 
  50.      * 
  51.      * @param key 
  52.      * @param object 
  53.      */  
  54.     public void setObject(String key, Object object) {  
  55.         SharedPreferences sp = this.context.getSharedPreferences(this.name, Context.MODE_PRIVATE);  
  56.   
  57.         //创建字节输出流  
  58.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  59.         //创建字节对象输出流  
  60.         ObjectOutputStream out = null;  
  61.         try {  
  62.             //然后通过将字对象进行64转码,写入key值为key的sp中  
  63.             out = new ObjectOutputStream(baos);  
  64.             out.writeObject(object);  
  65.             String objectVal = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));  
  66.             SharedPreferences.Editor editor = sp.edit();  
  67.             editor.putString(key, objectVal);  
  68.             editor.commit();  
  69.   
  70.         } catch (IOException e) {  
  71.             e.printStackTrace();  
  72.         } finally {  
  73.             try {  
  74.                 if (baos != null) {  
  75.                     baos.close();  
  76.                 }  
  77.                 if (out != null) {  
  78.                     out.close();  
  79.                 }  
  80.             } catch (IOException e) {  
  81.                 e.printStackTrace();  
  82.             }  
  83.         }  
  84.     }  
  85.   
  86.     @SuppressWarnings("unchecked")  
  87.     public  T getObject(String key, Class clazz) {  
  88.         SharedPreferences sp = this.context.getSharedPreferences(this.name, Context.MODE_PRIVATE);  
  89.         if (sp.contains(key)) {  
  90.             String objectVal = sp.getString(key, null);  
  91.             byte[] buffer = Base64.decode(objectVal, Base64.DEFAULT);  
  92.             //一样通过读取字节流,创建字节流输入流,写入对象并作强制转换  
  93.             ByteArrayInputStream bais = new ByteArrayInputStream(buffer);  
  94.             ObjectInputStream ois = null;  
  95.             try {  
  96.                 ois = new ObjectInputStream(bais);  
  97.                 T t = (T) ois.readObject();  
  98.                 return t;  
  99.             } catch (StreamCorruptedException e) {  
  100.                 e.printStackTrace();  
  101.             } catch (IOException e) {  
  102.                 e.printStackTrace();  
  103.             } catch (ClassNotFoundException e) {  
  104.                 e.printStackTrace();  
  105.             } finally {  
  106.                 try {  
  107.                     if (bais != null) {  
  108.                         bais.close();  
  109.                     }  
  110.                     if (ois != null) {  
  111.                         ois.close();  
  112.                     }  
  113.                 } catch (IOException e) {  
  114.                     e.printStackTrace();  
  115.                 }  
  116.             }  
  117.         }  
  118.         return null;  
  119.     }  
  120.   
  121.     /** 
  122.      * 对于外部不可见的过渡方法 
  123.      * 
  124.      * @param key 
  125.      * @param clazz 
  126.      * @param sp 
  127.      * @return 
  128.      */  
  129.     @SuppressWarnings("unchecked")  
  130.     private  T getValue(String key, Class clazz, SharedPreferences sp) {  
  131.         T t;  
  132.         try {  
  133.   
  134.             t = clazz.newInstance();  
  135.   
  136.             if (t instanceof Integer) {  
  137.                 return (T) Integer.valueOf(sp.getInt(key, 0));  
  138.             } else if (t instanceof String) {  
  139.                 return (T) sp.getString(key, "");  
  140.             } else if (t instanceof Boolean) {  
  141.                 return (T) Boolean.valueOf(sp.getBoolean(key, false));  
  142.             } else if (t instanceof Long) {  
  143.                 return (T) Long.valueOf(sp.getLong(key, 0L));  
  144.             } else if (t instanceof Float) {  
  145.                 return (T) Float.valueOf(sp.getFloat(key, 0L));  
  146.             }  
  147.         } catch (InstantiationException e) {  
  148.             e.printStackTrace();  
  149.             Log.e("system""类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");  
  150.         } catch (IllegalAccessException e) {  
  151.             e.printStackTrace();  
  152.             Log.e("system""类型输入错误或者复杂类型无法解析[" + e.getMessage() + "]");  
  153.         }  
  154.         Log.e("system""无法找到" + key + "对应的值");  
  155.         return null;  
  156.     }  
  157.   
  158.   
  159.   
  160. }  

为了区分于创建的sp对象,所以我是建议在给个context下都实例化这个工具对象,但是如果图方便,亦可以利用application来实现上下文的。

用法,由于我一个项目中需要创建了一个单例,所以我将单例的数据都封装在stateinfo实体 里面,点击储存时拿出对象存储,记得stateinfo一定要实现序列化接口,不然那会报空指针异常.

[html]  view plain  copy
  1. package com.nickming.cachedemo.ui;  
  2.   
  3. import android.os.Bundle;  
  4. import android.support.v7.app.AppCompatActivity;  
  5. import android.view.View;  
  6. import android.widget.Button;  
  7. import android.widget.TextView;  
  8.   
  9. import com.nickming.cachedemo.R;  
  10. import com.nickming.cachedemo.db.MTStateInfo;  
  11. import com.nickming.cachedemo.db.MTStateManager;  
  12. import com.nickming.cachedemo.utils.SaveObjectUtils;  
  13.   
  14. public class Main2Activity extends AppCompatActivity {  
  15.   
  16.     private Button mSave;  
  17.     private Button mShow;  
  18.     private TextView mResult;  
  19.     SaveObjectUtils utils;  
  20.     private static final String key=Main2Activity.class.getSimpleName();  
  21.   
  22.     @Override  
  23.     protected void onCreate(Bundle savedInstanceState) {  
  24.         super.onCreate(savedInstanceState);  
  25.         setContentView(R.layout.activity_main2);  
  26.   
  27.         mSave= (Button) findViewById(R.id.btn_save1);  
  28.         mResult= (TextView) findViewById(R.id.tv_result1);  
  29.         mShow= (Button) findViewById(R.id.btn_show1);  
  30.         utils=new SaveObjectUtils(this,key);  
  31.   
  32.         mSave.setOnClickListener(new View.OnClickListener() {  
  33.             @Override  
  34.             public void onClick(View v) {  
  35.   
  36.                 MTStateManager.getInstance().setTaskId(324444);  
  37.                 MTStateManager.getInstance().setBeginTime("20132003055");  
  38.                 MTStateInfo info=MTStateManager.getInstance().getStateInfo();  
  39.                 utils.setObject(""+info.getTaskId(),info);  
  40.             }  
  41.         });  
  42.         mShow.setOnClickListener(new View.OnClickListener() {  
  43.             @Override  
  44.             public void onClick(View v) {  
  45.                 MTStateInfo test=utils.getObject("324444",MTStateInfo.class);  
  46.                 MTStateManager.getInstance().clearDatas();  
  47.                 MTStateManager.getInstance().setDatas(test);  
  48.                 mResult.setText(""+MTStateManager.getInstance().getBeginTime());  
  49.             }  
  50.         });  
  51.     }  
  52.       
  53. }  
用sp存储对象最大好处就是不要新建好多张表,例如我的stateinfo里还有一个自定义的对象,用greendao时还需要再声明一次,但是用sp就不需要,他不管你是自定义的还是系统的,都能毫无差错的存储,我想这也是他的好处之一。

你可能感兴趣的:(android,基础)