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