-
Parcelable是 Android 的进程/组件间高性能序列化协议,主要用于把对象写入Parcel,在 组件间传递(Intent/Bundle)、跨进程通信(Binder/AIDL)、状态保存(如部分系统回调)中使用。 - 在现代 Android(含 API 35+)里,仍然推荐:组件间传递优先用
Parcelable(性能/体积/平台原生),而不是 JavaSerializable。
按“使用目的”划分(互斥、穷尽)
-
组件内/进程内传递
-
Activity/Service/BroadcastReceiver之间通过Intent.putExtra()、Bundle.putParcelable()传递对象 -
Fragment参数(arguments)或导航参数(底层也常走Bundle)
-
-
跨进程通信(IPC)
- Binder 事务中传输参数/返回值(AIDL 支持
Parcelable类型) - 注意:跨进程的
Parcelable更强调稳定性与版本兼容(字段增减策略)
- Binder 事务中传输参数/返回值(AIDL 支持
-
状态保存与恢复
- 一些系统/框架场景会要求把状态写入
Parcel(例如自定义View.BaseSavedState体系) - 这里的
Parcelable更像“状态快照”,字段一般更精简
- 一些系统/框架场景会要求把状态写入
按“实现方式”划分
-
手写实现(原生接口)
- 实现
Parcelable、writeToParcel()、describeContents()、以及CREATOR - 优点:可控、无需额外插件;缺点:样板代码多、易错(读写顺序/类型)
- 实现
-
Kotlin
@Parcelize(推荐主流方式)- Kotlin 插件生成
Parcelable实现,减少样板代码 - 优点:开发效率高、错误率低;缺点:需要 Kotlin/插件配置,某些复杂场景仍需自定义
Parceler
- Kotlin 插件生成
-
自动代码生成/编译期工具链(广义)
- 除
@Parcelize外,也可能用自研/三方生成器(但在新项目里一般不如@Parcelize直接)
- 除
按“数据结构类型”划分(你在业务里会遇到的几类)
-
纯值对象(POJO/数据类)
-
val id: Long, val name: String等:最适合Parcelable
-
-
包含集合/嵌套对象
-
List<Parcelable>、Map、嵌套 data class:可行,但要关注体积和深度
-
-
包含大对象/资源句柄
- 如大
Bitmap、大数组、文件内容:原则上不建议直接塞进Parcel(Binder 事务大小/内存抖动) - 更推荐传
Uri/文件路径/数据库 key,然后在目标端加载
- 如大
-
包含 Binder/FD 等“特殊资源”
- 某些类型需要
describeContents()返回CONTENTS_FILE_DESCRIPTOR(少见,但属于严格语义点)
- 某些类型需要
Parcel 的读写契约
-
Parcel本质是按顺序写入的二进制流:写的顺序 = 读的顺序(这是最常见 bug 源) -
CREATOR.createFromParcel(Parcel)用于反序列化;newArray用于数组创建 -
ClassLoader:反序列化嵌套类型时可能需要正确的ClassLoader(尤其在多模块/动态加载场景)
与 Serializable 的对比(实践结论)
- 性能:
Parcelable通常明显更快、更省内存(避免反射/对象图开销) - 兼容性:
Serializable版本演进依赖serialVersionUID等;Parcelable则是你自己维护读写顺序与默认值策略 - 结论:Android 组件传参/IPC 场景优先
Parcelable;仅在非常低频、简单、非性能敏感的场景才考虑Serializable
工程建议(面向 API 35+ 的现代写法)
- 传参“瘦身”:只传必要字段(id、token、uri),避免传大对象
- 演进策略:新增字段时放在末尾读取;读取时为旧版本缺失字段提供默认值(手写实现时尤其重要)
- 测试:对
Parcel循环(write→read)做单元测试,能快速发现顺序/类型错误
如果你希望我更贴近你的项目实践,我可以按同样的 MECE 框架再补一层:分别给出 @Parcelize 的最小示例、手写实现示例、以及 AIDL 里如何声明/传递 Parcelable(都按 minSdk 35 的语境组织)。
package demo
import android.content.Intent
import android.os.Bundle
import android.os.Parcelable
import androidx.activity.ComponentActivity
import kotlinx.parcelize.Parcelize
@Parcelize
data class User(
val id: Long,
val name: String
) : Parcelable
class SenderActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val user = User(id = 1L, name = "Alice")
val intent = Intent(this, ReceiverActivity::class.java).apply {
putExtra("extra_user", user)
}
startActivity(intent)
finish()
}
}
class ReceiverActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val user: User? = intent.getParcelableExtra("extra_user", User::class.java)
// user?.id / user?.name
}
}
- 这是最常见的
Parcelable场景:Activity之间通过Intent传一个data class - 关键点是 Kotlin 的
@Parcelize:编译期自动生成writeToParcel和CREATOR - 读取用 API 33+ 的新签名:
getParcelableExtra(key, User::class.java)(与你的minSdk=35完全匹配)
要让这段代码可编译,你的模块需要启用 Kotlin Parcelize 插件(Gradle 里加 plugins { id("kotlin-parcelize") } 或同等配置)。