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