在 Android 开发中,Parcelable 和 Serializable 是两种用于对象序列化的接口,但它们在设计目标、性能和使用场景上有显著差异。以下是它们的详细对比:
一、核心区别
特性 | Parcelable | Serializable |
---|---|---|
所属平台 | Android 特有 | Java 标准 |
设计目标 | 内存中的高效序列化(IPC 通信) | 通用对象序列化(存储/网络传输) |
实现复杂度 | 需手动实现 writeToParcel() 和 CREATOR |
仅需声明接口(可自动序列化) |
性能 | 高(显式操作,无反射) | 低(依赖反射,生成临时对象) |
适用场景 | Activity/Fragment 间传递数据 | 持久化存储(如文件、数据库)或网络传输 |
版本兼容性 | 需要手动处理字段顺序 | 依赖 serialVersionUID 控制版本 |
二、使用场景
-
选择 Parcelable:
- 高频数据传输:如 Activity 之间传递复杂对象。
- 性能敏感场景:避免因序列化导致界面卡顿(如大量数据传递)。
- Android 组件通信:Intent 中传递自定义对象。
-
选择 Serializable:
- 数据持久化:将对象保存到文件或数据库中。
- 网络传输:通过 HTTP 或 Socket 发送对象。
- 简单场景:快速实现序列化,无需处理复杂逻辑。
三、注意事项
Parcelable
- 字段顺序必须一致 :
在writeToParcel()
和CREATOR
中读写字段的顺序需严格一致,否则数据会错乱。 - 代码维护成本高 :
手动实现序列化逻辑,对象结构变化时需同步修改代码。 - 工具辅助 :
使用 Android Studio 插件(如 Parcelable Code Generator )或第三方库(如 Parceler)自动生成代码。
Serializable
- 版本兼容性问题 :
必须显式声明private static final long serialVersionUID
,否则类修改后可能导致反序列化失败。 - 性能陷阱 :
避免序列化大型对象或频繁调用,可能引发 GC 卡顿或 ANR。 - 安全风险 :
反序列化时可能执行恶意代码(需谨慎处理外部数据)。
四、如何选择?
-
优先 Parcelable:
- 所有 Android 组件间传递数据的场景。
- 对象需要高频传递或数据量较大(如 Bitmap 包装类)。
-
优先 Serializable:
- 需要将对象存储到文件或数据库。
- 与后端通信时传输数据(需确保双方使用相同序列化协议)。
- 快速原型开发,对性能不敏感。
五、示例代码
1. Parcelable 实现
kotlin
data class User(
val id: Int,
val name: String,
val email: String
) : Parcelable {
// 从 Parcel 中读取字段(顺序必须与 writeToParcel 一致)
constructor(parcel: Parcel) : this(
parcel.readInt(),
parcel.readString() ?: "",
parcel.readString() ?: ""
)
// 将字段写入 Parcel
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeInt(id)
parcel.writeString(name)
parcel.writeString(email)
}
override fun describeContents(): Int = 0
companion object CREATOR : Parcelable.Creator<User> {
override fun createFromParcel(parcel: Parcel): User = User(parcel)
override fun newArray(size: Int): Array<User?> = arrayOfNulls(size)
}
}
// 传递数据
val intent = Intent(this, DetailActivity::class.java)
intent.putExtra("user", user)
startActivity(intent)
2. Serializable 实现
kotlin
data class User(
val id: Int,
val name: String,
val email: String
) : Serializable {
// 显式声明 serialVersionUID(需通过工具生成或手动维护)
companion object {
private const val serialVersionUID: Long = 123456789L
}
}
// 存储到文件
val user = User(1, "Alice", "[email protected]")
val file = File(context.filesDir, "user.dat")
ObjectOutputStream(FileOutputStream(file)).use { it.writeObject(user) }
// 从文件加载
val loadedUser = ObjectInputStream(FileInputStream(file)).readObject() as User
六、高级优化
-
Parcelable 性能优化:
-
使用
@Parcelize
注解(需引入kotlin-parcelize
插件)自动生成代码。kotlin@Parcelize data class User(val id: Int, val name: String) : Parcelable
-
-
替代方案:
- JSON/Protobuf:网络传输时更高效。
- Room 或 Realm:直接存储对象到数据库,无需手动序列化。
七、总结
- Parcelable:是 Android 平台的高性能 IPC 通信首选,适合内存中数据传输。
- Serializable: 适用于持久化存储和兼容 Java 生态的场景,但需注意性能问题。
- 按需选择:结合具体场景,平衡性能、开发效率和可维护性。
更多分享
- Android跨进程通信中的关键字详解:in、out、inout、oneway
- Android Executor 与 Executors 详解 ------ 新手指南
- Kotlin 委托与扩展函数------新手入门
- Kotlin 作用域函数(let、run、with、apply、also)的使用指南
- 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
- Kotlin 扩展方法(Extension Functions)使用详解
- Kotlin 中 == 和 === 的区别
- Kotlin 操作符与集合/数组方法详解------新手指南
- Kotlin 中 reified 配合 inline 不再被类型擦除蒙蔽双眼
- Kotlin Result 类型扩展详解 ------ 新手使用指南