Parcel和Serializable的区别
Parcel
- 正常主动通过Parcel写入的数据,都是放在malloc分配的堆上的,这里也就没有特别的尺寸限制了。但并不是说对尺寸没要求,因为数据的接收端有要求!
- 这里Parcel只是对数据的打包类,在面向对象的抽象上,可以将可序列化的对象,flatten到一个parcel中通过binder传递。
- Parcel实际上是在内存中开辟了一段空间,通过writeXXX方法往这段空间中存放数据。
- 整个读写全是在内存中进行,主要是通过malloc()、realloc()、memcpy()等内存操作进行,所以效率比JAVA序列化中使用外部存储器会高很多;
Serializable
- 反序列化时用了大量反射
- Serializable被推荐为避免使用,原因是此方法序列化后的头部巨大、而且写数据特别慢
- Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC
- 内部实现是将Serializable写到字节数组byte[]里,在按照Parcel读写字节数组那样子来操作
- 只是在内存上操作的话 使用Parcelable 但如果涉及到io的话使用Serializable
- Serializable序列化之后的结果你可以放到任意的位置,内存、外存、网络,因为在Serializable之后的字节流中已经带上了足够的信息去进行验证一个需要反序列化的类是否满足定义。而Parcel虽然也是把数据转换成字节流,但是它的应用空间很窄,原因是在流中写入的类描述信息仅仅是一个类名,所以尽量不要用Parcel做持久化存储!!
- 也就是说,Serializable序列化的时候把类的信息(变量,方法等等,用于反序列化时的校验)也写出去了;而Parcel序列化的时候仅仅写出了类的名字,因此Parcel序列化的大小比Serializable小很多。
使用Parcel来写Serializable实际上先是通过将Serializable写到数组上,再通过写数组的方式来实现。
Parcel.Java
/**
* Write a generic serializable object in to a Parcel. It is strongly
* recommended that this method be avoided, since the serialization
* overhead is extremely large, and this approach will be much slower than
* using the other approaches to writing data in to a Parcel.
*/
public final void writeSerializable(Serializable s) {
if (s == null) {
writeString(null);
return;
}
String name = s.getClass().getName();
writeString(name);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(s);
oos.close();
writeByteArray(baos.toByteArray());
} catch (IOException ioe) {
throw new RuntimeException("Parcelable encountered " +
"IOException writing serializable object (name = " + name +
")", ioe);
}
}