话题:关于序列化的知识
1、Parcelable和Serializable有什么用,它们有什么差别?
(1) Parcelable的使用:
* public class MyParcelable implements Parcelable {
* private int mData;
*
* /*
* * Bit masks for use with {@link #describeContents}: each bit represents a
* * kind of object considered to have potential special significance when
* * marshalled.
* */
* public int describeContents() {
* //一共返回2种返回值 0 与 CONTENTS_FILE_DESCRIPTOR
* //一般返回0,特殊情况下返回CONTENTS_FILE_DESCRIPTOR
* return 0;
* }
*
* public void writeToParcel(Parcel out, int flags) {
* out.writeInt(mData);
* }
*
* public static final Parcelable.Creator<MyParcelable> CREATOR
* = new Parcelable.Creator<MyParcelable>() {
* public MyParcelable createFromParcel(Parcel in) {
* return new MyParcelable(in);
* }
*
* public MyParcelable[] newArray(int size) {
* return new MyParcelable[size];
* }
* };
*
* private MyParcelable(Parcel in) {
* mData = in.readInt();
* }
* }
通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象。也可以将Parcel看成是一个流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,只不过这个过程需要你来实现,因此写的顺序和读的顺序必须一致。
(2) Serializable的使用:
Serializable的实现,只需要implements Serializable 即可。这只是给对象打了一个标记,系统会自动将其序列化。
在序列化过程中会自动生成一个serialVersionUID来标识序列化对象。serialVersionUID是用来辅助序列化和反序列化过程的,序列化与反序列化的serialVersionUID必须相同才能够使序列化操作成功。
具体过程是这样的:序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
报出如下UID错误:
Exception in thread "main" java.io.InvalidClassException: com.android.test.Client;
local class incompatible: stream classdesc serialVersionUID =
-2656541345465468483
local class serialVersionUID = -1546464648434364595
(3)区别:
- Serializable接口(是JavaSE本身就支持的),Parcelable接口(是Android特有功能,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC))。
- 在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable
(4)选取原则:
- 在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
- Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。
- Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点, 也不提倡用,但在这种情况下,还是建议你用Serializable 。
2、自定义一个类让其实现Parcelable,大致流程是什么?
见答案1。
3、枚举如何实现Parcelable 接口
public enum Option implements Parcelable {
DATA_BASE("Database"), TRIPS("Trips");
private String option;
Option(String option){
this.option = option;
}
public String getName(){
return option;
}
private void setOption(String option){
this.option = option;
}
public static final Parcelable.Creator<Option> CREATOR = new Parcelable.Creator<Option>() {
public Option createFromParcel(Parcel in) {
Option option = Option.values()[in.readInt()];
option.setOption(in.readString());
return option;
}
public Option[] newArray(int size) {
return new Option[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(ordinal());
out.writeString(option);
}
}