Android序列化(Serializable/Parcelable)

1,872 阅读3分钟

blog.csdn.net/u013700502/…

一、什么是序列化?为什么要序列化?怎么进行序列化?

序列化定义:将一个类对象转换成可存储、可传输状态的过程。

序列化有两个过程:
1、序列化:将对象编码成字节流
2、反序列化:将字节流编码重新构建对象。
对象序列化后,可以在进程内/进程间、网络间进行传输,也可以做本地持久化存储。

为什么要序列化: 系统底层并不认识对象,数据传输是以字节序列形式传递,以进程间通信为例,需要将对象转化为字节序列(字节序列中包括该对象的类型,成员信息等),然后在目标进程里通过反序列化字节序列,将字节序列转换成对象。

序列化方式:
Serializable(Java提供 后面简称为S)
Parcelable(Android特有 下面简称为P)

二、Serializable

S是Java API,是一个通用的序列化机制,可以将对象序列化并保存在本地或内存中。S是一个空接口:

public interface Serializable {}

S只起到了一个标识的作用,用于告知程序实现了Serializable的对象是可以被序列化的,但真正进行序列化和反序列化的操作是通过ObjectOutputStream及ObjectInputStream实现的。

  • 类中由transient修饰的变量,不能被序列化,由static修饰,也不参与序列化过程

  • Serializable实现自定义序列化必须重写readObject、writeObject方法,可选readResolve、writeReplace方法

readResolve() 反序列化时执行,执行顺序在readObject之后 可以在此方法中重新生成一个新对象
writeReplace() 序列化时执行 执行顺序早于writeObject 可以在此方法中做一些替换

  • serialVersionUID 序列化会导致类的演变收到限制。每个可序列化的类都有一个唯一标识号与它相关(不指定系统会自动生成),sUID用来辅助序列化和反序列化的,序列化过程中会把类中的sUID写入序列化文件中。在反序列化时,检测序列化文件中sUID和当前类中的sUID是否一致,如果一致,才可以继续进行反序列化操作,否则说明序列化后类发生了一些改变,此时是不能反序列化的。

三、Parcelable

P是Android SDK API,其序列化操作完全由底层实现,可以在进程内、进程间(AIDL)高效传输数据。不宜做本地持久化存储。

  • createFromParcel()和writeToParcel()方法中对应变量读写的顺序必须是一致的,否则序列化会失败。
  • 序列化过程,首先写入序列化类名,然后调用类中复写的writeToParcel()方法依次写入
  • 反序列化过程,首先读取之前写入的类名,通过反射或缓存获取序列化类中的CREATOR,调用CREATOR中的createFromParcel进行反序列化

四、Parcelable、Serializable比较

S序列化和反序列化会经过大量的I/O操作,产生大量的临时变量引起GC;P是基于内存实现的封装和解封(marshalled& unmarshalled),效率比S快很多。

image.png

  • 下面两种成员变量不会参与到默认序列化过程中:
    1、static静态变量属于类而不属于对象
    2、transient标记的成员变量
  • 参与序列化的成员变量本身也是需要可序列化的
  • 反序列化时,非可序列化的(如被transient修饰)变量将会调用自身的无参构造函数重新创建,因此也要求此成员变量的构造函数必须是可访问的,否则会报错。