咱们知道SharedPreferences只能保存简单类型的数据,例如,String、int等。java
若是想用SharedPreferences存取更复杂的数据类型(类、图像等),就须要对这些数据进行编码。apache
咱们一般会将复杂类型的数据转换成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);
-
- String oAuth_Base64 = new String(Base64.encodeBase64(baos
- .toByteArray()));
- Editor editor = preferences.edit();
- editor.putString("oAuth_1", oAuth_Base64);
-
- editor.commit();
- } catch (IOException e) {
-
- }
- 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) {
-
- e.printStackTrace();
- }
- } catch (StreamCorruptedException e) {
-
- e.printStackTrace();
- } catch (IOException e) {
-
- e.printStackTrace();
- }
- return oAuth_1;
- }
须要导入一个包:commons-codec-1.4.jarspa
本文为《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类的代码:
.net
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文件中的代码以下:
code
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文件中的代码以下:
orm
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对象的代码以下:
xml
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组件上。
在 这里须要提一下的是图像选择。在本例中使用了res\drawable目录中的除了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>