安卓中,Serializable和Parcelable传递对象的区别(这里只指使用 Binder 跨进程传递对象),Binder 传递数据,要通过在Binder的onTransact和transact方法里,通过 Parcel 对象传递,而Parcel对象,只支持传递几种基本类型(与java基本数据类型有些差异,但请忽略这些细节,后面统称基本类型)。
对象发送时
- Parcelable使用者将组成对象的成员变量全部细化成基础数据类型,通过Parcel进而使用Binder传递,也就是如果成员变量不是基本类型,其也要实现Parcelable,直到全部都是基本类型,其传递的变量选择由使用者手动控制,所以其实现也更麻烦,这个过程就是程序员用Parcel往Binder装数据。
- 而Serializable要先用流将整个对象转为byte数组,再用Binder将这个byte数组作为基本类型传递,这个过程由Parcel封装,所以其使用简单,不需要手写代码往Parcel里面装数据,Parcel封装了将Serializable对象序列化成byte数组的过程。
对象接收时
- Parcelable 可以根据使用者的定义来创建对象,可以直接使用构造函数创建(在Creator的createFromParcel),用Parcel从Binder中取出数据来初始化这个对象。
- Serializable 对象接收时是把Binder传递过来的byte数组通过流转为对象,这个过程也是Parcel封装的,其消耗更大,但使用者代码量很少(几乎什么都不用写)。
简单的来说,Parcelable对象发送时,由使用者将要传递的数据写进Parcel对象再传递至Binder中,对象接收时,使用者用 Parcel 从 Binder 中取值,完成对象的创建以及成员变量的赋值,使用者要清楚自己写值和取值的顺序。
Serializable 对象发送时,使用者只需要实现 Serializable 接口,因为 Binder 只传递基本类型,Parcel 先将Serializable 对象序列化,整个转为 byte 数组,然后通过 Binder 传递。对象接收时,通过 Parcel 从 Binder 读出 byte 数组,再反序列化成对象,这个过程也是 Parcel 封装的,所以使用者几乎什么都不用做。
异同
- 两者数据都要用 Binder 传递,接收对象时其实还都要用到反射(用Parcelable只是有可能用到反射,在androidstudio 生成的parcelable实现中,对于对象反序列化时拿T.CREATOR 对象其实用到反射拿到的,尽管这不是必须的)
- Parcelable 的使用由程序员从对象抽出数据写入 Binder,在 Binder 另一端将零散的数据再组合成对象,而Serializable 由 Parcel 完成整个对象数据的打包,打包成一个 byte 数组,再在 Binder 的另一端解包再合成对象,所以使用者只操作对象而不具体操作数据。
Binder 读写数据的两个过程中,Serializable 用到的中间对象更多,浪费的空间更多,传递的数据更大,浪费的时间也更多,但 Serializable 的好处,就是使用更简单,而且可以脱离 Binder 使用,比如可以存对象到文件,或用 socket 传递对象,而 Parcelable 是完全依赖 Binder 的,Binder 负责数据的传递,而数据的提取和组合是使用者完成的,当然,现在这些工作可以由插件工具一键生成,但这就是在代码编写阶段的事情了(其实要想利用其他传输机制实现 Parcelable 对象传递也是可以的,只要你能为其他机制实现一个拥有Parcel相同能力的类),