Android序列化

Android平台序列化接口有Serializable和Parcelable。

Serializable

Serializable翻译过来是“可串行的”,主要用于传统java的序列化,可以序列化类到磁盘、网络传输等等。使用方法也很简单,直接实现Serializable接口即可。

Serializable对象一般和ObjectInputStream/ObjectOutputStream配合使用,关键方法readObject和writeObject。

序列化的过程我们不用管,不过要注意,静态变量和声明了transient关键字的变量不会被序列化。

我们可以定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//只是一个sample,实际方法可以自己实现
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.defaultWriteObject();
oos.writeInt(data);
System.out.println("session serialized");
}
private void readObject(ObjectInputStream ois) throws IOException,
ClassNotFoundException {
ois.defaultReadObject();
data = ois.readInt();
activationTime = System.currentTimeMillis();
System.out.println("session deserialized");
}

这两个方法可以自定义序列化和反序列化过程,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文件编译后生成的代码中会有:

1
2
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();

这两句代码生成了两个Parcel,一个用于client向server传输数据的序列化,一个用于server向client传输数据的反序列化。

writeToParcel(Parcel dest, int flags)

我们在实现一个Parcelable对象时会复写这个方法,这个方法传入了一个Parcel实例,由Parcel序列化每一个成员变量。

createFromParcel(Parcel in)

这个是CREATOR的一个方法,通过实现这个方法来定义反序列化的规则。实际上就是new了一个对象,然后初始化的过程。

总结

Parcel传输数据是通过Binder驱动进行的,所以只会有一次数据拷贝(内存映射机制)。其整个过程是在内存中进行。序列化和反序列化由用户定义,避免了反射的过程。序列化的过程有序,不需要写入变量名,所以数据量也比较小。其整体性能要大大的优于Serializable的方式。

文章目录
  1. 1. Serializable
    1. 1.1. Externalizable
  2. 2. Parcelable
    1. 2.1. Parcel
    2. 2.2. writeToParcel(Parcel dest, int flags)
    3. 2.3. createFromParcel(Parcel in)
  3. 3. 总结
|