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