Parcelable 和 Serializable 的区别详解 —— 新手指南

在 Android 开发中,ParcelableSerializable 是两种用于对象序列化的接口,但它们在设计目标、性能和使用场景上有显著差异。以下是它们的详细对比:

一、核心区别

特性 Parcelable Serializable
所属平台 Android 特有 Java 标准
设计目标 内存中的高效序列化(IPC 通信) 通用对象序列化(存储/网络传输)
实现复杂度 需手动实现 writeToParcel()CREATOR 仅需声明接口(可自动序列化)
性能 (显式操作,无反射) (依赖反射,生成临时对象)
适用场景 Activity/Fragment 间传递数据 持久化存储(如文件、数据库)或网络传输
版本兼容性 需要手动处理字段顺序 依赖 serialVersionUID 控制版本

二、使用场景

  • 选择 Parcelable

    • 高频数据传输:如 Activity 之间传递复杂对象。
    • 性能敏感场景:避免因序列化导致界面卡顿(如大量数据传递)。
    • Android 组件通信:Intent 中传递自定义对象。
  • 选择 Serializable

    • 数据持久化:将对象保存到文件或数据库中。
    • 网络传输:通过 HTTP 或 Socket 发送对象。
    • 简单场景:快速实现序列化,无需处理复杂逻辑。

三、注意事项

Parcelable

  1. 字段顺序必须一致
    writeToParcel()CREATOR 中读写字段的顺序需严格一致,否则数据会错乱。
  2. 代码维护成本高
    手动实现序列化逻辑,对象结构变化时需同步修改代码。
  3. 工具辅助
    使用 Android Studio 插件(如 Parcelable Code Generator )或第三方库(如 Parceler)自动生成代码。

Serializable

  1. 版本兼容性问题
    必须显式声明 private static final long serialVersionUID,否则类修改后可能导致反序列化失败。
  2. 性能陷阱
    避免序列化大型对象或频繁调用,可能引发 GC 卡顿或 ANR。
  3. 安全风险
    反序列化时可能执行恶意代码(需谨慎处理外部数据)。

四、如何选择?

  • 优先 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", "alice@example.com")
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 生态的场景,但需注意性能问题。
  • 按需选择:结合具体场景,平衡性能、开发效率和可维护性。

更多分享

  1. Android跨进程通信中的关键字详解:in、out、inout、oneway
  2. Android Executor 与 Executors 详解 ------ 新手指南
  3. Kotlin 委托与扩展函数------新手入门
  4. Kotlin 作用域函数(let、run、with、apply、also)的使用指南
  5. 一文带你吃透Kotlin中 lateinit 和 by lazy 的区别和用法
  6. Kotlin 扩展方法(Extension Functions)使用详解
  7. Kotlin 中 == 和 === 的区别
  8. Kotlin 操作符与集合/数组方法详解------新手指南
  9. Kotlin 中 reified 配合 inline 不再被类型擦除蒙蔽双眼
  10. Kotlin Result 类型扩展详解 ------ 新手使用指南
相关推荐
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
1点东西1 天前
做了近两年的Agent开发,其实真正要学的就是这五件事
llm·agent·ai编程
七牛云行业应用1 天前
Qwen-Image-2.1 开源部署完整指南:Diffusers、ComfyUI 与推理服务
ai编程
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
福如意如我心意1 天前
TencentDB Agent Memory和其他开源memory
ai编程
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
豆包MarsCode1 天前
AI 圈爆火的 Jev 是什么?如何在 TraeCode 中使用
trae