zoukankan      html  css  js  c++  java
  • android SharedPreferences 存储对象

    我们知道SharedPreferences只能保存简单类型的数据,例如,String、int等。

    如果想用SharedPreferences存取更复杂的数据类型(类、图像等),就需要对这些数据进行编码。

    我们通常会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在 XML文件中。

    [java] view plaincopy
     
    1. public void saveOAuth(OAuthV1 oAuth_1) {  
    2.     SharedPreferences preferences = getSharedPreferences("base64",  
    3.             MODE_PRIVATE);  
    4.     // 创建字节输出流  
    5.     ByteArrayOutputStream baos = new ByteArrayOutputStream();  
    6.     try {  
    7.         // 创建对象输出流,并封装字节流  
    8.         ObjectOutputStream oos = new ObjectOutputStream(baos);  
    9.         // 将对象写入字节流  
    10.         oos.writeObject(oAuth_1);  
    11.         // 将字节流编码成base64的字符窜  
    12.         String oAuth_Base64 = new String(Base64.encodeBase64(baos  
    13.                 .toByteArray()));  
    14.         Editor editor = preferences.edit();  
    15.         editor.putString("oAuth_1", oAuth_Base64);  
    16.   
    17.         editor.commit();  
    18.     } catch (IOException e) {  
    19.         // TODO Auto-generated  
    20.     }  
    21.     Log.i("ok""存储成功");  
    22. }  


    之后将其解码:

    [java] view plaincopy
     
    1. public OAuthV1 readOAuth() {  
    2.     OAuthV1 oAuth_1 = null;  
    3.     SharedPreferences preferences = getSharedPreferences("base64",  
    4.             MODE_PRIVATE);  
    5.     String productBase64 = preferences.getString("oAuth_1""");  
    6.               
    7.     //读取字节  
    8.     byte[] base64 = Base64.decodeBase64(productBase64.getBytes());  
    9.       
    10.     //封装到字节流  
    11.     ByteArrayInputStream bais = new ByteArrayInputStream(base64);  
    12.     try {  
    13.         //再次封装  
    14.         ObjectInputStream bis = new ObjectInputStream(bais);  
    15.         try {  
    16.             //读取对象  
    17.             oAuth_1 = (OAuthV1) bis.readObject();  
    18.         } catch (ClassNotFoundException e) {  
    19.             // TODO Auto-generated catch block  
    20.             e.printStackTrace();  
    21.         }  
    22.     } catch (StreamCorruptedException e) {  
    23.         // TODO Auto-generated catch block  
    24.         e.printStackTrace();  
    25.     } catch (IOException e) {  
    26.         // TODO Auto-generated catch block  
    27.         e.printStackTrace();  
    28.     }  
    29.     return oAuth_1;  
    30. }  

     需要导入一个包: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对象。

    mySharedPreferences = getSharedPreferences("base64",Activity.MODE_PRIVATE);

    其中mySharedPreferences是在类中定义的SharedPreferences类型变量。

    在保存Product对象之前,需要创建Product对象,并将相应组件中的值赋给Product类的相应属性。将Product对象保存在XML文件中的代码如下:

    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组件上。

    在 这里需要提一下的是图像选择。在本例中使用了resdrawable目录中的除了icon.png外的其他图像。为了能列出这些图像,本例使用了 Java的反射技术来枚举这些图像的资源ID。基本原理是枚举R.drawable类中所有的Field,并获得这些Field的值。如果采用这个方法, 再向drawable目录中添加新的图像,或删除以前的图像,并不需要修改代码,程序就可以显示最新的图像列表。枚举图像资源ID的代码如下:

    // 获得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文件,会看到如下的内容:

    <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
    <map>
    <string name="productImage">/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABDsyj7yK3</string>
    <string name="product">rO0ABXNyABtuZXQuYmxvZ2phdmEubW9iaWxlLlByb2</string>
    </map>
  • 相关阅读:
    用到的一些方法
    Android屏蔽Home键
    Android自定义GridView显示一行,并且可以左右滑动
    模糊匹配字母大小写
    Android四大组件之Content Provider的学习
    用于小数据存储的SharedPreferences
    Android小知识点
    【译】用C/C++操作链表
    和好友的QQ记录,多关注哈需要关怀的人
    岁不待人_20080321
  • 原文地址:https://www.cnblogs.com/weixiao870428/p/3673600.html
Copyright © 2011-2022 走看看