Parcel类和Parcelable接口

202 阅读4分钟

Parcel类和Parcelable接口

Parcel - Android中文版 - API参考文档

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),你也可以根据需要定义自己的标志。

image.png 可是相比于java.io.Serializable更快,and why?

● 在 Android 中比 Serializable 更快的原因主要是因为它避免了反射的开销,提供了更高效的内存操作,允许开发者控制序列化过程

what

容器用于可以通过IBinder发送的消息(数据和对象引用)。 一个包裹可以同时包含在IPC的另一侧(使用这里用于编写特定类型的各种方法,或者一般的Parcelable接口)的Parcelable - Android中文版 - API参考文档数据,以及引起另一侧接收的对象的活动IBinder - Android中文版 - API参考文档一个代理IBinder与包裹中的原始IBinder连接。

why

  1. 数据传输

在 Android 中,组件之间的通信通常需要传递数据。例如,当你启动一个新的活动时,你可能需要将一些数据传递给它。Parcelable 接口和 Parcel 类提供了一种高效的方式来实现这一点。不禁让人想起Bundle

  1. 性能

高效性:Parcelable 是 Android 特有的序列化机制,专为 Android 设计,性能优于 Java 的 Serializable。Parcelable 通过直接操作内存来序列化对象,避免了反射的开销,因此在性能上更优。

内存管理:Parcel 允许你在内存中高效地打包和解包数据,适合在 Android 的 IPC(进程间通信)中使用。

  1. 灵活性

自定义序列化:通过实现 Parcelable 接口,你可以控制对象的序列化过程,选择哪些字段需要被序列化,如何序列化等。这种灵活性使得你可以根据需要优化数据传输。

支持复杂数据结构:Parcelable 可以处理复杂的数据结构,包括嵌套对象和集合等。

  1. 适用场景

活动之间的传递:当你通过 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) {
                // 压缩数据并写入
                // 这里可以实现压缩逻辑
            }
        }
    }