Serializable - Java原生的序列化方案
Parcelable - android提供的序列化方案
Serializable接口的使用
空接口,类只需要声明 implements Serializable, 并提供一个serialVersionUID值即可.
使用ObjectOutputStreamd和ObjectInputStream就可以把一个对象写入文件和从文件读取出来.
写入文件:
LoggingInfo logInfo = new LoggingInfo("MIKE", "MECHANICS");
FileOutputStream fos = new FileOutputStream("c:\\logging.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(logInfo);
oos.close();
读取文件:
FileInputStream fis = new FileInputStream("c:\\logging.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
LoggingInfo info = (LoggingInfo) ois.readObject();
ois.close();
提供serialVersionUID值的目的
系统序列化和反序列化时, 使用这个值来判断在这2次操作之间, 类的结构是否发生了变化。
如果不提供这个值的话, 系统会根据当前类的结构自动生成serialVersionUID值,如果serialVersionUID的值发生了变化,
或者即便serialVersionUID两次相同, 但由于类结构发生的变化(例如:改变了类中某个成员变量的类型)导致无法完成反序列化操作, 系统会报异常终止操作.
静态成员变量和transient标记的变量不参与序列化
静态成员变量属于类不属于对象, 因此不参与序列化过程.
有些敏感变量值, 比如用户的密码不希望被序列化, 就可以用transient标记而不参与序列化.
Parcelable接口的使用
使用起来稍显复杂, 需要自己实现3个方法:
writeToParcel(Parcel dest, int flags)
内部接口Creator里的createFromParcel(Parcel source)
describeContents()
Demo:
public class MyParcelable implements Parcelable {
private int mData;
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mData); //通过Parcel的一系列write方法实现序列化
}
public static final Parcelable.Creator<MyParcelable> CREATOR
= new Parcelable.Creator<MyParcelable>() {
public MyParcelable createFromParcel(Parcel in) {
return new MyParcelable(in);//内部实现上, 通过Parcel的一系列read方法实现反序列化
}
public MyParcelable[] newArray(int size) {
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in) {
mData = in.readInt();
}
}
Parcelable接口最常见的用处.
如果某个类的对象需要设置给Intent中的Bundle对象, 那么这个类要实现Parcelable或Serializable接口.
通常基于效率考虑, 这个类选择实现Parcelable接口.
public class Intent implements Parcelable, Cloneable {
private Bundle mExtras;
public Intent putExtra(String name, Parcelable value) {
mExtras.putParcelable(name, value);
return this;
}
public Intent putExtra(String name, Serializable value) {
mExtras.putSerializable(name, value);
return this;
}
}
Bundle其实就是一个保存K,V数据的Map.
/**
* Bundle Class
* A mapping from String K to various Parcelable types V.
*
*/
public final class Bundle extends BaseBundle implements Cloneable, Parcelable {
}
Serializable接口和Parcelable接口都能实现序列化,选择哪个?
Parcelable主要用于把对象序列化后,以K,V的形式设置给intent中的bundle.这个intent对象携带着这个数据,
传递给其他进程使用, 实现跨进程的数据传递.
Intent intent = new Intent();
intent.putExtra("downloadParam", mDownloadParam);
虽然通过Parcelable也可以实现把对象写入存储设备或是把对象序列化后通过网络传输,
但实现起来比较复杂, 因此这两种情况下一般还是使用Serializable接口.
Android里面为什么要设计出Bundle而不是直接让Intent使用Map结构承载数据
Map里实现了Serializable接口,而Bundle实现了Parcelable的接口.
基于执行效率的考虑(比 JDK 自带的 Serializable 效率高),让Intent使用Bundle结构.
宏观上说, Bundle实际上就是一个特殊的Map.
intent传递数据时,数据大小的限制在1Mb以内
因此不要使用intent直接传递bitmap对象, 否则容易发生crash.
详见:
http://blog.csdn.net/a568078283/article/details/46681321
----DONE.-----------