首页 > 代码库 > 数据存储(一)--SharedPreferences之你不知道的事

数据存储(一)--SharedPreferences之你不知道的事

一、SharedPreferences将数据文件保存在指定路径上

SharedPreferences原则上是只能保存在当前应用程序私有的shared_prefs目录中,不过也不是绝对的,我们可以用一些非常规的方法改变存储目录,反射技术是很好的选择。

先上实现代码:

private  SharedPreferences share;
private  SharedPreferences.Editor editor;

修改路径关键代码:

private void initSharedPreferences(String path,String name,int mode)
	{
		try {
	 		Field field =ContextWrapper.class.getDeclaredField("mBase");
			field.setAccessible(true);
			Object obj = field.get(this);
			field = obj.getClass().getDeclaredField("mPreferencesDir");
			field.setAccessible(true);
			File file = new File(path);
			field.set(obj, file);
			share = getSharedPreferences(name, mode);
			editor = share.edit();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
Field field =ContextWrapper.class.getDeclaredField("mBase");
获取ContextWrapper对象中的mBase变量,该变量保存了ContextImpl对象,ContextImpl对象中的mPreferencesDir保存了数据文件的保存路径。

share = getSharedPreferences(name, mode);
执行这句后会在指定目录下创建文件用来保存数据。


PS:使用反射技术,要求仔细研究源码,这样才会知道要去修改哪个地方,哪个变量。

使用:

		initSharedPreferences("/data/fly","config",Activity.MODE_PRIVATE);
		editor.putString("AA", "AAaa");
		editor.commit();
		Toast.makeText(this, share.getString("AA", ""), 1000).show();



二、SharedPreferences保存图片

SharedPreferences原则上只能将字符串以key-value的形式保存,但是我们可以采用编码的方式将任何二进制数据转化为字符串,从而将可以将二进制数据保存在SharedPreferences文件中,最常用的编码格式是Base64.

private void saveDrawable(int id)
    {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), id);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.JPEG, 50, baos);
        String imageBase64 = new String(Base64.encodeToString(baos.toByteArray(),Base64.DEFAULT));
        editor.putString("P",imageBase64 );
        editor.commit();
    }
    
    private Drawable loadDrawable()
    {
        String temp = share.getString("P", "");
        ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decode(temp.getBytes(), Base64.DEFAULT));
        return Drawable.createFromStream(bais, "");
    }


三、SharedPreferences保存对象

由于二进制数据经过编码后可以用SharedPreferences以字符串的形式存储,所以保存对象也称为可能。

private void saveProduct(Product product)
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		try {
			ObjectOutputStream oos = new ObjectOutputStream(baos);
			oos.writeObject(product);
			String temp = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));
			Log.i("AAA", temp);
			editor.putString("product", temp);
			editor.commit();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private Product getProduct()
	{
		String temp = share.getString("product", "");
		ByteArrayInputStream bais =  new ByteArrayInputStream(Base64.decode(temp.getBytes(), Base64.DEFAULT));
		Product product = null;
		try {
			ObjectInputStream ois = new ObjectInputStream(bais);
			product = (Product) ois.readObject();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			Log.i("AAA", e.toString());
		}catch(ClassNotFoundException e1)
		{
			Log.i("AAA", e1.toString());
		}
		return product;
	}

对象可以被SharedPreferences存储的前提是该对象被序列化了,也就是说要实现Serializable接口,实际上Serializable接口是个空接口,只是为了标记该对象是被序列化的。

public static class Product implements Serializable
	{
		String name;
		String id;
		int count;
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public String getId() {
			return id;
		}
		public void setId(String id) {
			this.id = id;
		}
		public int getCount() {
			return count;
		}
		public void setCount(int count) {
			this.count = count;
		}
		
		public String toString()
		{
			return "name:"+name+" id:"+id+" count:"+count;
		}

	}

如果该类是内部类的话要写成static 不然会出现java.io.NotSerializableException异常:解决办法点这里