Android中实现序列化有两个选择:一个是实现Serializable接口,Java提供的一个序列化接口;另一个是实现Parcelable接口,Android特有的序列化接口,效率比实现Serializable接口高效,可用于Intent数据传递,也可以用于进程间通信(IPC)。
序列化和反序列化
序列化:用来处理对象流的机制,所谓对象流就是将对象的内容进行流化。方便对流化后的对象进行读写操作,也可在网络间传输。简单来说是一种将对象以一连串的字节描述的过程。
反序列化:将流化后的对象重新构成对象的过程。
序列化应用场景
- 永久性保存对象,保存对象的字节序列到本地文件中
- 通过序列化对象在网络中传输
- 通过序列化在进程间传递对象
Serializable序列化ID:
序列化ID serialVersionUID的值可以是固定的1L,也可以是随机生成一个不重复的long类型数据,甚至可以不声明也可以实现序列化。但是会对反序列化过程产生影响,因为不同的序列化ID之间不能进行序列化和反序列化。
Serializable实现序列化步骤
创建某些OutputStream对象:OutputStream outputStream = new FileOutputStream("output.txt");
将其封装到ObjectOutputStream对象内:ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
调用writeObject()即可完成对象的序列化,并将其发送给OutputStream:objectOutputStream.writeObject(Object);
关闭资源:objectOutputStream.close()和outputStream.close();
Serializable实现反序列化步骤
创建某些InputStream对象:InputStream inputStream = new FileInputStream("output.txt");
将其封装到ObjectInputStream对象内:ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
调用readObject()即可完成对象的反序列化:object = objectInputStream.readObject();
关闭资源:objectInputStream.close()和inputStream.close();
注意:
- 静态变量属于类不属于对象,所以不会参与序列化过程。
- 用transient关键字标记的成员变量不参与序列化过程。(通过用这个关键字可以控制想要序列化的成员变量)
Serializable代码实例:
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name= name;
this.age= age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// Serializable:把对象序列化
public static void writeSerializableObject() {
try {
Person person = new Person("Mary", 18);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("output.txt"));
objectOutputStream.writeObject(person);
objectOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// Serializable:反序列化对象
public static void readSerializableObject() {
try {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("output.txt"));
Person person = (Person) objectInputStream.readObject();
objectInputStream.close();
System.out.println("name = " + person.getName() + ", age = " + person.getAge());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Parcelable接口定义
public interface Parcelable
{
//内容描述接口,基本不用管
public int describeContents();
//写入接口函数,打包
public void writeToParcel(Parcel dest, int flags);
//读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入
//为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例
public interface Creator<T>
{
public T createFromParcel(Parcel source);
public T[] newArray(int size);
}
}
Parcelable实现序列化步骤
实现Parcelable接口
重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据
重写describeContents方法,内容接口描述,默认返回0就可以
实例化静态内部对象CREATOR实现接口Parcelable.Creator。需重写本接口中的两个方法:createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size]),供外部类反序列化本类数组使用。
public static final Parcelable.Creator<T> CREATOR
Parcelable代码实例:
public class Person implements Parcelable
{
private String name;
private String sex;
private int age;
public int describeContents()
{
return 0;
}
public void writeToParcel(Parcel out, int flags)
{
out.writeString(name);
out.writeString(sex);
out.writeInt(age);
}
public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>()
{
public Person createFromParcel(Parcel in)
{
return new Person(in);
}
public Person[] newArray(int size)
{
return new Person[size];
}
};
private Person(Parcel in)
{
name = in.readString();
sex = in.readString();
age = in.readInt();
}
}
Serializable和Parcelable对比
Serializable实现较简单,只需要implements Serializable即可,系统会自动将其序列化;而Parcelable的实现,不仅需要implements Parcelable,还需要在类中添加一个静态成员变量CREATOR,这个变量需要实现 Parcelable.Creator接口。
使用内存时,Parcelable比Serializable性能高,推荐使用Parcelable。
Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。