转自博客:http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html
1、实现序列化的作用
数据的传递在应用中是必要的,然而普通的数据传递只是支持基本数据类型,如String, int ,或者更高些的数据类型,如arraylist,Object等。但是开发中,我们往往需要传递对象,来达到便利的数据传输目的,这就需要实现对象的序列化。
数据的传递包括本地数据存取,网络数据传输,以及Intent数据传输等。
2、实现序列化的方法
1) Parcelable
2)Serializable
3、序列化使用原则
1) 使用内存时,Parcelable效率要高于Serializable,所以推荐使用Parcelable。
2) Serializable在序列化的同时会产生大量临时变量,从而引起频繁的GC。
3) Parcelable不能使用在将数据保存在磁盘上,因此此时建议使用Serializable。
4、Serializable
Serializable的实现,只需要 implements Serializable即可,系统会自动将其序列化
5、Parcelable
1) implements Parcelable
2) 重写describeContents、writeToParcel两个方法,writeToParcel用于将当前对象映射为Parcel对象
@Override
public int describeContents() {
// 内容描述接口,默认返回0即可
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// 将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中
dest.writeString(id);
dest.writeString(path);
dest.writeString(thumbnailPath);
bitmap.writeToParcel(dest, 0);
}
3)创建Parcelable.Creator对象,并重写createFromParcel、newArray方法;createFromParcel用于将Parcel对象映射为你的对象
public static final Parcelable.Creator<ImageItem> CREATOR = new Parcelable.Creator<ImageItem>() {
@Override
public ImageItem createFromParcel(Parcel source) {
ImageItem item = new ImageItem();
item.id = source.readString();
item.path = source.readString();
item.thumbnailPath = source.readString();
item.bitmap = Bitmap.CREATOR.createFromParcel(source);
return item;
}
@Override
public ImageItem[] newArray(int size) {
return new ImageItem[size];
}
};
所以Parcelable的用法可以总结为implements Parcelable接口,然后加上将你的对象封装为Parcel对象的writeToParcel方法,附带描述的describeContents;然后加上将Parcel对象映射为你的对象的Parcel.Creator对象,并重写映射方法即可。
注意事项:
1)writeToParcel与createFromParcel两个方法添加与取出变量的顺序要一致
2)Bitmap对象的操作,要采用 bitmap.writeToParcel(dest, 0) 与 Bitmap.CREATOR.createFromParcel(source)
3)Parcel.Creator的创建保持不变 public static final Parcelable.Creator<ImageItem> CREATOR = new Parcelable.Creator<ImageItem>() ,最好只替换<T>部分
4)Bitmap的传递,大小限制为40KB
5)Parcel对List的读写:dest.writeList(photoItems) 与 source.readList(this.photoItems, ImageItem.class.getClassLoader())。代码如下:
public List<ImageItem> photoItems = new ArrayList<ImageItem>();
//Parcel读取构造
public ImageFolder (Parcel source){
source.readList(this.photoItems, ImageItem.class.getClassLoader());
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(photoItems);
}
public static final Parcelable.Creator<ImageFolder> CREATOR = new Creator<ImageFolder>() {
@Override
public ImageFolder[] newArray(int size) {
return new ImageFolder[size];
}
@Override
public ImageFolder createFromParcel(Parcel source) {
return new ImageFolder(source);
}
};
如上代码,写入一个自定义对象的List可通过writeList实现;由于List本身已被序列化,所以读取List可通过readList。其中readList的参数,
参数1:对象中的List本身,如photoItems
参数2: List中的对象的ClassLoader,如List<ImageItem> photoItems,List的对象为ImageItem,因此参数为ImageItem.class.getClassLoader()
源码:
public class ImageItem implements Parcelable {
/**
* Image ID
*/
public String id;
/**
* Image路径
*/
public String path;
/**
* Image缩略路径
*/
public String thumbnailPath;
/**
* Image位图
*/
public Bitmap bitmap;
/**
* 根据路径获取Bitmap
*
* @param reqWidth
* @param reqHeight
* @return
*/
public Bitmap getBitmap(int reqWidth, int reqHeight) {
return ImageResizer.decodeSampledBitmapFromFile(path, reqWidth,
reqHeight);
}
@Override
public int describeContents() {
// 内容描述接口,默认返回0即可
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// 将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从
// Parcel容器获取数据
dest.writeString(id);
dest.writeString(path);
dest.writeString(thumbnailPath);
bitmap.writeToParcel(dest, 0);
}
/**
* 将Parcle对象映射为我的对象
*/
public static final Parcelable.Creator<ImageItem> CREATOR = new Parcelable.Creator<ImageItem>() {
@Override
public ImageItem createFromParcel(Parcel source) {
ImageItem item = new ImageItem();
item.id = source.readString();
item.path = source.readString();
item.thumbnailPath = source.readString();
item.bitmap = Bitmap.CREATOR.createFromParcel(source);
return item;
}
@Override
public ImageItem[] newArray(int size) {
return new ImageItem[size];
}
};
}