Parcel类和Parcelable接口
Parcelable - Android中文版 - API参考文档
前言:
版本兼容性:由于 Parcel 的序列化格式是 Android 内部实现的一部分,任何 Android 版本的更新都可能导致序列化格式的变化。这就是为什么将 Parcel 数据存储在持久性存储中是不推荐的原因。
自定义对象:对于自定义对象,开发者需要确保在 writeToParcel() 和 CREATOR 中的实现保持一致,以避免在对象的字段或类型发生变化时导致读取失败。
Parcel 的序列化格式并没有一个公开的、标准化的文档,因为它是 Android 平台内部实现的一部分。Parcel 主要用于在 Android 组件之间传递数据(例如,Activity、Service、BroadcastReceiver 等),其序列化和反序列化过程是由 Android 框架处理的。
writeToParcel的Flag是用于确认信息,其实自己也可以自定义:
在 Android 中,writeToParcel 方法的 flags 参数可以用于传递一些自定义的标志,以控制对象的序列化行为。虽然 Android 提供了一些预定义的标志(如 PARCELABLE_WRITE_RETURN_VALUE),你也可以根据需要定义自己的标志。
可是相比于java.io.Serializable更快,and why?
● 在 Android 中比 Serializable 更快的原因主要是因为它避免了反射的开销,提供了更高效的内存操作,允许开发者控制序列化过程
what
容器用于可以通过IBinder发送的消息(数据和对象引用)。 一个包裹可以同时包含在IPC的另一侧(使用这里用于编写特定类型的各种方法,或者一般的Parcelable接口)的Parcelable - Android中文版 - API参考文档数据,以及引起另一侧接收的对象的活动IBinder - Android中文版 - API参考文档一个代理IBinder与包裹中的原始IBinder连接。
why
- 数据传输
在 Android 中,组件之间的通信通常需要传递数据。例如,当你启动一个新的活动时,你可能需要将一些数据传递给它。Parcelable 接口和 Parcel 类提供了一种高效的方式来实现这一点。不禁让人想起Bundle
- 性能
高效性:Parcelable 是 Android 特有的序列化机制,专为 Android 设计,性能优于 Java 的 Serializable。Parcelable 通过直接操作内存来序列化对象,避免了反射的开销,因此在性能上更优。
内存管理:Parcel 允许你在内存中高效地打包和解包数据,适合在 Android 的 IPC(进程间通信)中使用。
- 灵活性
自定义序列化:通过实现 Parcelable 接口,你可以控制对象的序列化过程,选择哪些字段需要被序列化,如何序列化等。这种灵活性使得你可以根据需要优化数据传输。
支持复杂数据结构:Parcelable 可以处理复杂的数据结构,包括嵌套对象和集合等。
- 适用场景
活动之间的传递:当你通过 Intent 启动一个活动时,可以将 Parcelable 对象作为额外数据传递。
服务与活动之间的通信:在服务和活动之间传递数据时,可以使用 Parcelable。
保存状态:在配置更改(如屏幕旋转)时,可以使用 Parcelable 来保存和恢复活动的状态。
how
大部分的Parcel API都围绕着读写各种类型的数据。 这些功能有六大类可用。
最基本的数据功能是写入和读取原始数据类型: writeByte(byte) , readByte() , writeDouble(double) , readDouble() , writeFloat(float) , readFloat() , writeInt(int) , readInt() , writeLong(long) , readLong() , writeString(String) , readString() 。 大多数其他数据操作都建立在这些之上。 给定数据使用主机CPU的字节进行写入和读取
记得注意写入读出顺序:
class AttachContentType() : Parcelable {
private var name: String? = null
private var age: Int? = null
constructor(parcel: Parcel) : this() {
this.name = parcel.readString()
this.age = parcel.readInt()
}
// 自定义标志
companion object {
const val FLAG_INCLUDE_METADATA = 1 // 包含元数据的标志
const val FLAG_COMPRESS_DATA = 2 // 压缩数据的标志
@JvmField
val CREATOR: Parcelable.Creator<AttachContentType> =
object : Parcelable.Creator<AttachContentType> {
override fun createFromParcel(parcel: Parcel): AttachContentType {
return AttachContentType(parcel)
}
override fun newArray(size: Int): Array<AttachContentType?> {
return arrayOfNulls(size)
}
}
}
override fun describeContents(): Int {
return 0
}
override fun writeToParcel(dest: Parcel, flags: Int) {
// 根据自定义标志进行处理
if (flags and FLAG_INCLUDE_METADATA != 0) {
// 写入元数据
name?.let {
dest.writeString(name)
}
}
if (flags and FLAG_COMPRESS_DATA != 0) {
// 压缩数据并写入
// 这里可以实现压缩逻辑
}
}
}