Parcelable接口
Parcelable是android.io包下的接口,是Android中推荐使用的序列化接口。
只要实现Parcelable接口的类,就可以使用Parcel进行序列化和反序列化操作。
实现Pacelable接口
|
|
Parcel是什么
Parcel简单来说是一套机制。可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象。
Parcel的读写源码
Parcel.writeParcelable
|
|
这里需要注意的是,每一个Parcelable对象在写入流之前,都会在前面首先写入这个对象的ClassName,主要是方便后面读的时候,能够知道是哪个类,感觉这个地方还是做的比较粗糙,在Serializable中对应一个序列化类的信息刻画比这简单的一个类名要靠谱得多,所以官方文档上才会说,如果你想进行持久化存储,那么Parcelable不是你的菜,道理很简单,这里不会有任何版本的概念,只要你的类名不改,旧版本的数据就可以被新版本的class进行反序列化,然而class里面的属性可能已经完全不一样了。
Parcel.readParcelable
|
|
|
|
Serializable接口
Serializable是java.io包下的一个接口,是Java类进行序列化和反序列化的标记接口。
一个类实现了Serializable接口,就可以被ObjectOutputStream和ObjectInputStream进行序列化和反序列化的操作。
被transient描述的属性或类的静态变量是不会被序列化的。
如果一个实现了Serializable接口的类,继承了另外一个类。那么这个类的父类,必须继承Serializable或者提供一个空构造方法。
反序列化产生的对象并不是通过构造器创造的,所以依赖构造器保证的约束条件在对象反序列化时都无法保证。比如一个设计成单利的类,如果能序列化,那么可以反序列化出N个对象。
序列化和反序列化中隐藏的方法
具体的方法修饰符,private protected public 都可以,序列化和反序列化都是通过反射来调用的。
private Object writeReplace() throws ObjectStreamException ObjectOutPutStream
在序列化一个对象时,会首先调用这个方法,此方法中可以替换原有序列化的对象。
private void writeObject(java.io.ObjectOutputStream out) throws IOException
调用ObjectOutputStream.defaultWriteObject()使用的是默认的序列化过程,在调用defaultWriteObject方法后,可以往out流中写入一些数据,在readObject中可以读取。
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException
在writeObject中写入的数据,在此方法中需要以写入顺序读取,同时我们注意到这里已经把参数inputstream回调给我们了,我们可以在这个位置注册一个回调,可以在validateObject方法中检查这个反序列化对象是否合法。
private Object readResolve() throws ObjectStreamException
此方法中可以替换反序列化出来的对象。
实现Serializable接口
|
|
自定义Serializable序列化
ObjectOutputStream的defaultWriteObject和defaultReadObject,是通过反射的方式实现序列化和反序列化的。
这种默认方式,会导致效率上比Android的Parcelable慢。
但是如果通过自己实现writeObject和readObject,那么在效率上会比Parcelable快。点击链接,查看测试结果
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 public class TreeNode implements Serializable, Parcelable {private static final long serialVersionUID = 1L;public List<TreeNode> children;public String string0;public String string1;public String string2;public int int0;public int int1;public int int2;public boolean boolean0;public boolean boolean1;public boolean boolean2;public TreeNode() {}protected TreeNode(Parcel in) {if (in.readByte() == 0x01) {children = new ArrayList<TreeNode>();in.readList(children, TreeNode.class.getClassLoader());} else {children = null;}string0 = in.readString();string1 = in.readString();string2 = in.readString();int0 = in.readInt();int1 = in.readInt();int2 = in.readInt();boolean0 = in.readByte() != 0x00;boolean1 = in.readByte() != 0x00;boolean2 = in.readByte() != 0x00;}private void writeObject(ObjectOutputStream out) throws IOException {out.writeUTF(string0);out.writeUTF(string1);out.writeUTF(string2);out.writeInt(int0);out.writeInt(int1);out.writeInt(int2);out.writeBoolean(boolean0);out.writeBoolean(boolean1);out.writeBoolean(boolean2);if (children != null) {out.writeInt(children.size());for (TreeNode child : children) {child.writeObject(out);}} else {out.writeInt(0);}}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {string0 = in.readUTF();string1 = in.readUTF();string2 = in.readUTF();int0 = in.readInt();int1 = in.readInt();int2 = in.readInt();boolean0 = in.readBoolean();boolean1 = in.readBoolean();boolean2 = in.readBoolean();int childCount = in.readInt();if (childCount > 0) {children = new ArrayList<TreeNode>(childCount);for (int i = 0; i < childCount; i++) {TreeNode child = new TreeNode();child.readObject(in);children.add(child);}}}@Overridepublic int describeContents() {return 0;}@Overridepublic void writeToParcel(Parcel dest, int flags) {if (children == null) {dest.writeByte((byte) (0x00));} else {dest.writeByte((byte) (0x01));dest.writeList(children);}dest.writeString(string0);dest.writeString(string1);dest.writeString(string2);dest.writeInt(int0);dest.writeInt(int1);dest.writeInt(int2);dest.writeByte((byte) (boolean0 ? 0x01 : 0x00));dest.writeByte((byte) (boolean1 ? 0x01 : 0x00));dest.writeByte((byte) (boolean2 ? 0x01 : 0x00));}public static final Parcelable.Creator<TreeNode> CREATOR = new Parcelable.Creator<TreeNode>() {@Overridepublic TreeNode createFromParcel(Parcel in) {return new TreeNode(in);}@Overridepublic TreeNode[] newArray(int size) {return new TreeNode[size];}};}