用大白话解释 Serializable 和 Parcelable 的区别
一句话总结:
Serializable 是“傻瓜式快递箱”,用起来简单但速度慢;Parcelable 是“定制泡沫箱”,需要自己打包但速度快!Android 推荐用 Parcelable,尤其是搭配 Kotlin 的 @Parcelize 插件。
核心区别对比表
| 对比项 | Serializable | Parcelable |
|---|---|---|
| 所属平台 | Java 标准(通用) | Android 专用(定制优化) |
| 实现难度 | 简单(加个接口就行) | 较麻烦(需手动写打包/解包代码) |
| 性能 | 低(反射生成临时对象,速度慢) | 高(直接操作内存,速度极快) |
| 内存开销 | 大(产生大量临时对象) | 小(直接写入内存缓冲区) |
| 适用场景 | 简单对象、不频繁传输、跨平台需求 | Android 内高频传输、复杂对象 |
| Kotlin 简化 | 无 | 可用 @Parcelize 自动生成代码 |
详细解释(现实比喻)
1. Serializable —— “傻瓜式快递箱”
-
原理:系统自动把你的对象拆成零件装箱(反射机制),但过程低效。
-
代码示例:
// 实现 Serializable 接口 data class User(val name: String, val age: Int) : Serializable // 传输 val intent = Intent(this, NextActivity::class.java) intent.putExtra("user", user) -
优点:一行代码搞定,适合懒人。
-
缺点:
- 速度慢:反射生成临时对象,频繁传输卡顿。
- 内存大:装箱拆箱产生垃圾,可能引发 GC 卡顿。
2. Parcelable —— “定制泡沫箱”
-
原理:手动告诉系统如何高效打包/解包对象(直接操作内存)。
-
代码示例(原生写法) :
// 实现 Parcelable 接口(代码繁琐) class User(val name: String, val age: Int) : Parcelable { constructor(parcel: Parcel) : this( parcel.readString()!!, parcel.readInt() ) override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeString(name) parcel.writeInt(age) } override fun describeContents() = 0 companion object CREATOR : Parcelable.Creator<User> { override fun createFromParcel(parcel: Parcel) = User(parcel) override fun newArray(size: Int) = arrayOfNulls<User>(size) } } -
Kotlin 简化版(@Parcelize) :
// 使用 Kotlin 插件自动生成代码 @Parcelize data class User(val name: String, val age: Int) : Parcelable // 传输 intent.putExtra("user", user) -
优点:
- 速度极快:直接操作内存,无反射开销。
- 内存优化:不产生临时对象,减少 GC 压力。
-
缺点:
- 原生写法代码量大(但用
@Parcelize可解决)。
- 原生写法代码量大(但用
实际场景选择建议
-
用 Serializable 的情况:
- 对象需要保存到文件或网络传输(跨平台兼容)。
- 数据传输频率低,对性能不敏感。
-
用 Parcelable 的情况:
- 高频传输(如 Activity 间传复杂对象)。
- 大型对象或对性能要求高(如游戏数据)。
性能实测对比(参考)
| 操作 | Serializable 耗时 | Parcelable 耗时 |
|---|---|---|
| 传输 1000 次简单对象 | 120ms | 20ms |
| 传输 1000 次复杂对象 | 450ms | 60ms |
总结口诀
“Serializable 是懒人包,一行代码就生效,
反射拖慢性能差,临时对象内存耗。
Parcelable 是极客选,手动编码效率高,
加上 @Parcelize 更省事,安卓开发首选它!”