Android 序列化 Serializable 和 Parcelable
文章目录
一、什么是序列化
序列化 (Serialization) 将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。远程处理使用序列化“通过值”在计算机或应用程序域之间传递对象。
二、序列化方法
- Serialization 是 Java 所提供的序列化接口,它是一个空的接口,只为对象提供标准的序列表和反序列化操作。
- Parcelable Android 特有的序列化接口。
1、Serialization 接口
Serializable
是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
Serializable
特点:
- 简单易用,只需要实体类继承
Serializable
即可 - 可序列化类中,未实现
Serializable
的属性状态无法被序列化/反序列化 - 一个实现序列化的类,它的子类也是可序列化的
Serializable
序列化实例:
public class User implements Serializable {
private static final long serialVersionUID = 123456789L;
private int userId;
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
序列化和反序列化的过程
// 序列化过程
User user = new User(1, "张三");
ObjectOutputStream objectOutputStream;
{
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("cache.txt"));
objectOutputStream.writeObject(user);
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 反序列化过程
ObjectInputStream objectInputStream;
{
try {
objectInputStream = new ObjectInputStream(new FileInputStream("cache.txt"));
try {
User newUser = (User) objectInputStream.readObject();
objectInputStream.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
从上面的实例可以看出Serializable
序列化很简单,只需要设置一个serialVersionUID
即可。
其中serialVersionUID
可以设置,也可以不设置,如果不进行设置系统也会生成默认的值,那么为什么一定要设置serialVersionUID
的值呢。serialVersionUID
的详细工作机制是这样的:序列化的时候系统会把当前列的serialVersionUID
写入序列化的文件中(也可能是其他的中介),当反序列化的时候系统会去检测文中的serialVersionUID
,看他是否和当前类的serialVersionUID
一致,如果一致就说明序列化的类和的版本和当前类的版本是相同的,这个时候可以成功反序列化,否则就说明当前类和序列化的类相比发生了某些变化,比如当前类或成员变量发生了变化系统就会重新计算当前类的hash值并把它赋值给serialVersionUID
,这个时候当前类的serialVersionUID
就和序列化数据中的serialVersionUID
不一致,于是反序列化就会失败,程序就会出现InvalidClassException
错误。所以为了避免反序列化的失败尽量手动设置serialVersionUID
的值。
2、Parcelable 接口
Parcelable
接口是 Android 专用的序列化接口,在性能上完胜Serializable
接口。
Parcelable
特点:
- 比起 Serializable,Parcelable 开销更小效率更高。
- 序列化过程较复杂。其实实现 Parcelable 接口的方法是可以用插件直接生成的。
- Parcelable 实现主要还是解决 Android 平台内存紧缺的问题。
Parcelable
序列化实例:
public class User implements Parcelable {
private int userId;
private String userName;
public User(int userId, String userName) {
this.userId = userId;
this.userName = userName;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
/**
* 自动创建的的构造器,使用反序列化得到的 Parcel 构造对象,
* 从序列化后的对象中创建原始对象
* @param in
*/
protected User(Parcel in) {
userId = in.readInt();
userName = in.readString();
}
/**
* 内容描述
* @return
*/
@Override
public int describeContents() {
//几乎都返回 0,除非当前对象中存在文件描述符时为 1
return 0;
}
/**
* 序列化,将当前对象写入序列化结构中,其中flags标识有两种值:0或者1,
* 为1时标识当前对象需要作为返回值返回,不能立即释放资源,几乎所有情况都为0
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(userId);
dest.writeString(userName);
}
/**
* 反序列化
*/
public static final Creator<User> CREATOR = new Creator<User>() {
/**
* 反序列创建对象,从序列化后的对象中创建原始对象
* @param in
* @return
*/
@Override
public User createFromParcel(Parcel in) {
return new User(in);
}
/**
* 反序列创建对象数组,创建指定长度的原始对象数组
* @param size
* @return
*/
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
三、Serializable 和 Parcelable 优缺点:
Serializable
序列化- 代码量少,写起来方便。
- 使用反射机制序列化过程较慢,序列化时会创建许多临时对象,容易触发垃圾回收。
Parcelable
序列化- 代码量比较多
- 速度快,效率高。实现原理是将一个完整的对象进行分解,分解后的每一个部分都是Intent所支持的数据类型。
(完)