Android平台序列化接口有Serializable和Parcelable。
Serializable
Serializable翻译过来是“可串行的”,主要用于传统java的序列化,可以序列化类到磁盘、网络传输等等。使用方法也很简单,直接实现Serializable接口即可。
Serializable对象一般和ObjectInputStream/ObjectOutputStream配合使用,关键方法readObject和writeObject。
序列化的过程我们不用管,不过要注意,静态变量和声明了transient关键字的变量不会被序列化。
我们可以定义:
这两个方法可以自定义序列化和反序列化过程,ObjectInput/OutputStream会通过反射调用这两个方法,从而实现了自定义过程。
serialVersionUID是一个long型的static常量,序列化前后的UID声明要保持一致,否则会导致序列化失败。这个值可以自动生成也可以自己定义。
序列化到本地是二进制串,实际上是键值对。
Externalizable
这个接口继承了Serializable接口,提供了writeExternal和readExternal方法,相当于上面的writeObject和readObject方法的功能。只不过将其标准化了而已。
Parcelable
Parcelable对象的序列化在内存中进行。Parcelable对象是Android进程间通信的数据的载体。Parcelable接口比Serializable接口复杂了很多,开发者必须要实现接口定义的方法。并定义自己序列化的过程。
Parcel
Parcel是包裹的意思,所有的Parcelable对象最后都是通过Parcel来进行序列化的。
Parcel的实例化是在IPC的过程中进行的,可以看到AIDL文件编译后生成的代码中会有:
这两句代码生成了两个Parcel,一个用于client向server传输数据的序列化,一个用于server向client传输数据的反序列化。
writeToParcel(Parcel dest, int flags)
我们在实现一个Parcelable对象时会复写这个方法,这个方法传入了一个Parcel实例,由Parcel序列化每一个成员变量。
createFromParcel(Parcel in)
这个是CREATOR的一个方法,通过实现这个方法来定义反序列化的规则。实际上就是new了一个对象,然后初始化的过程。
总结
Parcel传输数据是通过Binder驱动进行的,所以只会有一次数据拷贝(内存映射机制)。其整个过程是在内存中进行。序列化和反序列化由用户定义,避免了反射的过程。序列化的过程有序,不需要写入变量名,所以数据量也比较小。其整体性能要大大的优于Serializable的方式。