我们知道SharedPreferences只能保存简单类型的数据,例如,String、int等。
如果想用SharedPreferences存取更复杂的数据类型(类、图像等),就需要对这些数据进行编码。
我们通常会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在 XML文件中。
public void saveOAuth(OAuthV1 oAuth_1) { SharedPreferences preferences = getSharedPreferences("base64", MODE_PRIVATE); // 创建字节输出流 ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { // 创建对象输出流,并封装字节流 ObjectOutputStream oos = new ObjectOutputStream(baos); // 将对象写入字节流 oos.writeObject(oAuth_1); // 将字节流编码成base64的字符窜 String oAuth_Base64 = new String(Base64.encodeBase64(baos .toByteArray())); Editor editor = preferences.edit(); editor.putString("oAuth_1", oAuth_Base64); editor.commit(); } catch (IOException e) { // TODO Auto-generated } Log.i("ok", "存储成功"); }之后将其解码:
public OAuthV1 readOAuth() { OAuthV1 oAuth_1 = null; SharedPreferences preferences = getSharedPreferences("base64", MODE_PRIVATE); String productBase64 = preferences.getString("oAuth_1", ""); //读取字节 byte[] base64 = Base64.decodeBase64(productBase64.getBytes()); //封装到字节流 ByteArrayInputStream bais = new ByteArrayInputStream(base64); try { //再次封装 ObjectInputStream bis = new ObjectInputStream(bais); try { //读取对象 oAuth_1 = (OAuthV1) bis.readObject(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (StreamCorruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return oAuth_1; }
需要导入一个包:commons-codec-1.4.jar
本文为《Android/OPhone开发完全讲义》一书的内容连载。转载请注明出处
我们知道SharedPreferences只能保存简单类型的数据,例如,String、int等。如果想用SharedPreferences存取更 复杂的数据类型(类、图像等),就需要对这些数据进行编码。我们通常会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在 XML文件中。
Android SDK中并未提供Base64编码和解码库。因此,需要使用第三方的jar包。在本例中使用了Apache Commons组件集中的Codec组件进行Base64编码和解码。读者可以从如下的地址下载Codec组件的安装包。
http://commons.apache.org/codec/download_codec.cgi
在Android工程目录的lib子目录中已经包含了Codec组件的jar包(commons-codec-1.4.jar),因此,读者可以在该工程中直接使用Codec组件。
在本例中将一个Product类的对象实例和一个图像保存在XML文件中,并在程序重新运行后从XML文件装载Product对象和图像。下面是Product类的代码:
package net.blogjava.mobile; import java.io.Serializable; // 需要序列化的类必须实现Serializable接口 public class Product implements Serializable { private String id; private String name; private float price; // 此处省略了属性的getter和setter方法在存取数据之前,需要使用下面的代码创建一个SharedPreferences对象。
Product product = new Product(); product.setId(etProductID.getText().toString()); product.setName(etProductName.getText().toString()); product.setPrice(Float.parseFloat(etProductPrice.getText().toString())); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); // 将Product对象放到OutputStream中 oos.writeObject(product); mySharedPreferences = getSharedPreferences("base64", Activity.MODE_PRIVATE); // 将Product对象转换成byte数组,并将其进行base64编码 String productBase64 = new String(Base64.encodeBase64(baos.toByteArray())); SharedPreferences.Editor editor = mySharedPreferences.edit(); // 将编码后的字符串写到base64.xml文件中 editor.putString("product", productBase64); editor.commit();保存图像的方法与保存Product对象的方法类似。由于在保存之前,需要选择一个图像,并将该图像显示在ImageView组件中,因此,从ImageView组件中可以直接获得要保存的图像。将图象保存在XML文件中的代码如下:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 将ImageView组件中的图像压缩成JPEG格式,并将压缩结果保存在ByteArrayOutputStream对象中 ((BitmapDrawable) imageView.getDrawable()).getBitmap().compress(CompressFormat.JPEG, 50, baos); String imageBase64 = new String(Base64.encodeBase64(baos.toByteArray())); // 保存由图像字节流转换成的Base64格式字符串 editor.putString("productImage", imageBase64); editor.commit();
其中compress方法的第2个参数表示压缩质量,取值范围是0至100,0表示最高压缩比,但图像效果最差,100则恰恰相反。在本例中取了一个中间值50。
从XML文件中装载Product对象和图像是保存的逆过程。也就是从XML文件中读取Base64格式的字符串,然后将其解码成字节数组,最后将字节数组转换成Product和Drawable对象。装载Product对象的代码如下:
String productBase64 = mySharedPreferences.getString("product", ""); // 对Base64格式的字符串进行解码 byte[] base64Bytes = Base64.decodeBase64(productBase64.getBytes()); ByteArrayInputStream bais = new ByteArrayInputStream(base64Bytes); ObjectInputStream ois = new ObjectInputStream(bais); // 从ObjectInputStream中读取Product对象 Product product = (Product) ois.readObject();装载图像的代码如下:
String imageBase64 = mySharedPreferences.getString("productImage",""); base64Bytes = Base64.decodeBase64(imageBase64.getBytes()); bais = new ByteArrayInputStream(base64Bytes); // 在ImageView组件上显示图像 imageView.setImageDrawable(Drawable.createFromStream(bais,"product_image"));在上面的代码中使用了Drawable类的createFromStream方法直接从流创建了Drawable对象,并使用setImageDrawable方法将图像显示在ImageView组件上。
// 获得R.drawable类中所有的Field Field[] fields = R.drawable.class.getDeclaredFields(); for (Field field : fields) { if (!"icon".equals(field.getName())) imageResIdList.add(field.getInt(R.drawable.class)); }运行本例后,单击【选择产品图像】按钮,会显示一个图像选择对话框,如图1所示。选中一个图像后,关闭图像选择对话框,并单击【保存】按钮。如果保存成功,将显示如图2所示的提示对话框。当再次运行程序后,会显示上次成功保存的数据。
查看base64.xml文件,会看到如下的内容: