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

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

       1.存储List类型的数据

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

      (1)List

      (2)List>

      (3)List

      处理的方式时用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  void setDataList(String tag, List 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  List getDataList(String tag) {  
            List datalist=new ArrayList();  
            String strJson = preferences.getString(tag, null);  
            if (null == strJson) {  
                return datalist;  
            }  
            Gson gson = new Gson();  
            datalist = gson.fromJson(strJson, new TypeToken>() {  
            }.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 listBean;  
        private ArrayList listString;  
        private ArrayList> 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();  
            listBean = new ArrayList();  
            listMap = new ArrayList>();  
        }  
      
        @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 map=new HashMap();  
                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 getValue(String key, Class 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 getObject(String key, Class 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 getValue(String key, Class 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就不需要,他不管你是自定义的还是系统的,都能毫无差错的存储

你可能感兴趣的:(android)