Parcelable
和 Bundle
对象旨在用于跨进程边界(例如 IPC/Binder 事务)、活动之间的 Intent 以及在配置更改之间存储瞬态状态。此页面提供了使用 Parcelable
和 Bundle
对象的建议和最佳实践。
注意:Parcel
不是通用序列化机制,您永远不应该将任何 Parcel
数据存储在磁盘上或通过网络发送。
在活动之间发送数据
当应用创建 Intent
对象以在 startActivity(android.content.Intent)
中启动新的 Activity 时,应用可以使用 putExtra(java.lang.String, java.lang.String)
方法传入参数。
以下代码段显示了如何执行此操作的示例。
Kotlin
val intent = Intent(this, MyActivity::class.java).apply { putExtra("media_id", "a1b2c3") // ... } startActivity(intent)
Java
Intent intent = new Intent(this, MyActivity.class); intent.putExtra("media_id", "a1b2c3"); // ... startActivity(intent);
操作系统会打包 Intent 的底层 Bundle
。然后,操作系统创建新的活动,解包数据并将 Intent 传递给新活动。
建议您使用 Bundle
类来设置操作系统已知的 Intent
对象上的基本类型。 Bundle
类针对使用 Parcel 进行编组和解组进行了高度优化。
在某些情况下,您可能需要一种机制来在活动之间发送复合或复杂对象。在这种情况下,自定义类应实现 Parcelable,并提供相应的 writeToParcel(android.os.Parcel, int)
方法。它还必须提供一个名为 CREATOR
的非空字段,该字段实现 Parcelable.Creator
接口,其 createFromParcel()
方法用于将 Parcel
转换回当前对象。有关更多信息,请参阅 Parcelable
对象的参考文档。
通过 Intent 发送数据时,应注意将数据大小限制在几 KB 以内。发送过多的数据可能会导致系统抛出 TransactionTooLargeException
异常。
进程间发送数据
进程间发送数据类似于在活动之间发送数据。但是,在进程间发送数据时,建议不要使用自定义 Parcelable。如果从一个应用发送自定义 Parcelable
对象到另一个应用,则需要确保发送和接收应用都存在完全相同的自定义类版本。通常,这可以是两个应用都使用的公共库。如果您的应用尝试向系统发送自定义 Parcelable,则可能会发生错误,因为系统无法反序列化它不了解的类。
例如,某个应用可能会使用 AlarmManager
类设置闹钟,并在闹钟 Intent 上使用自定义 Parcelable
。当闹钟响起时,系统会修改 Intent 的 Bundle
附加数据以添加重复次数。此修改可能导致系统从附加数据中剥离自定义 Parcelable
。反过来,当应用收到修改后的闹钟 Intent 时,可能会导致应用崩溃,因为应用期望接收不再存在的额外数据。
Binder 事务缓冲区具有有限的固定大小,目前为 1MB,该缓冲区由进程正在进行的所有事务共享。由于此限制是在进程级别而不是在每个活动级别,因此这些事务包括应用中的所有 Binder 事务,例如 onSaveInstanceState、startActivity 和与系统的任何交互。当大小限制超出时,将抛出 TransactionTooLargeException。
对于 savedInstanceState 的特定情况,应将数据量保持较小,因为系统进程需要在用户可以导航回该活动(即使活动进程被终止)的整个时间内保留提供的数据。建议您将保存的状态数据量保持在 50k 以下。
注意:在 Android 7.0(API 级别 24)及更高版本中,系统会将 TransactionTooLargeException 作为运行时异常抛出。在较低版本的 Android 中,系统仅在 logcat 中显示警告。