文章目录
序列化
为什么要序列化
在进行 Android 开发的时候,无法将对象的引用传递给 Activity 或者 Fragment,我们需要将这些对象放到一个 Intent 或者 Bundle 里面,然后进行传递。但是 Intent 或者是 Bundle 中只能存放进行过序列化后的对象。
什么是序列化
序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
反序列化
反序列化就是序列化的逆过程,将网络上传输的字节流、本地存储的文件中的内容读取转换为一个对象的过程。
怎么实现序列化
Android 中 Intent 如果要传递类对象,可以通过两种方式。
- 方式一:Serializable,要传递的类实现 Serializable 接口
- 方式二:Parcelable,要传递的类实现 Parcelable 接口
Serializable(Java 自带的)
Serializable 是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。 Serializable 接口是一种标识接口,也就是无需实现方法,Java 便会对这个对象进行序列化操作。
serialVersionUID 的作用
- 类的 serialVersionUID 的默认值完全依赖于 Java 编译器的实现,对于同一个类,用不同的 Java 编译器编译,也有可能会导致不同的serialVersionUID。所以 IDE 才会提示声明 serialVersionUID 的值。
- 不定义 serialVersionUID 时,Java 会根据类的细节自动生成 serialVersionUID 的值,如果对类的源码做了修改,再重新编译,生成的类的 serialVersionUID 的取值可能会变化,再次反序列化时,若 serialVersionUID 不相等会 crash。
- 不修改 serialVersionUID,但是 bean 的属性发生改变,则反序列化时此属性会为空,读不到值(取兼容老版本的作用)
- 只要反序列化时 serialVersionUID 不相等,就会
InvalidClassException Crash
Parcelable(Android 专用)
除了 Serializable 之外,使用 Parcelable 也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable 方式的实现原理是将一个完整的对象进行分解, 而分解后的每一部分都是 Intent 所支持的数据类型
,这样也就实现传递对象的功能了。
两者的区别
两者最大的区别在于存储媒介的不同 ,Serializable
使用 I/O 读写存储在硬盘上。而 Parcelable
是直接 在内存中读写。很明显,内存的读写速度通常大于 IO 读写,所以在 Android 中传递数据优先选择 Parcelable。
Serializable
会使用反射,序列化和反序列化过程需要大量 I/O 操作,序列化过程中会创建很多临时对象,容易触发垃圾回收;Parcelable
自已实现封送和解封(marshalled &unmarshalled)操作,不需要用反射,数据也存放在内存中,效率要快很多。
继承一个实现了 Parcelable 接口的类需要注意的地方
B 类实现了 Parcelable 接口,A 继承自 B,则 A 不需要再实现 Parcelable 接口,但是 A 需要实现相应的抽象方法:describeContents、writeToParcel 还有 CREATOR 构造器等等。还要在 writeToParcel 和相应的构造函数中调用 super 方法。如下,CourseEvent 实现了 Parcelable 接口。
CourseEvent 类:
public class CourseEvent extends ResponseEvent implements Parcelable {
protected List<CourseInfoDto> cList; //课程列表
protected long currentTime; //socket发送时间戳
public CourseEvent() {
}
protected CourseEvent(Parcel in) {
cList = in.createTypedArrayList(CourseInfoDto.CREATOR);
currentTime = in.readLong();
}
public static final Creator<CourseEvent> CREATOR = new Creator<CourseEvent>() {
@Override
public CourseEvent createFromParcel(Parcel in) {
return new CourseEvent(in);
}
@Override
public CourseEvent[] newArray(int size) {
return new CourseEvent[size];
}
};
@Override
public String toString() {
return "CourseEvent{" +
" cList=" + cList +
", currentTime=" + currentTime +
'}';
}
public List<CourseInfoDto> getcList() {
return cList;
}
public void setcList(List<CourseInfoDto> cList) {
this.cList = cList;
}
public long getCurrentTime() {
return currentTime;
}
public void setCurrentTime(long currentTime) {
this.currentTime = currentTime;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedList(cList);
dest.writeLong(currentTime);
}
}
WgtCourseInfo 类:
public class WgtCourseInfo extends CourseEvent {
private int cState; //0:没上过任何课;1:上课中;2:下课啦
public WgtCourseInfo() {
super();
}
protected WgtCourseInfo(Parcel in) {
super(in);
cState = in.readInt();
}
public static final Creator<WgtCourseInfo> CREATOR = new Creator<WgtCourseInfo>() {
@Override
public WgtCourseInfo createFromParcel(Parcel in) {
return new WgtCourseInfo(in);
}
@Override
public WgtCourseInfo[] newArray(int size) {
return new WgtCourseInfo[size];
}
};
@Override
public String toString() {
return "WgtCourseInfo{" +
"cState=" + cState +
", cList=" + cList +
", currentTime=" + currentTime +
'}';
}
public int getcState() {
return cState;
}
public void setcState(int cState) {
this.cState = cState;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(cState);
}
}
要记住一点,在 writeToParcel 中write 数据的顺序,要与在构造器中 read 的顺序相同。
参考网站
序列化Serializable和Parcelable的理解和区别
Extending a class that implements Parcelable
How to extend android class which implements Parcelable interface?
Is using Serializable in Android bad?
Android - Problem with the Serializable interface