Parcelable Vs Serializable

今天说一下对象序列化时的两个接口SerializableParcelable,前者是Java中的老面孔了,大家也都非常熟悉了,后者是Android提供的新面孔,既然Java本身就有序列化的接口为什么Android还要重新造轮子呢?当然Google也不是傻子,肯定是前面那个轮子不能满足他们的要求,所以他们才重新造出了Parcelable这个接口。

Serializable接口的使用

首先来看看Serializable如何使用。

lang: java
1
2
3
4
5
6
7
8
9
10
11
public class SerializableClass implements Serializable{
String name;
int age;
float height;
List<Skill> skillList;

static class Skill implements Serializable{
String skillName;
boolean gotIt;
}
}

好了,这样就可以直接将这个类序列化后使用Intent/Bundle进行传递了。使用起来非常简单,只需要实现Serializable接口即可。Serializable接口是一个标志接口,只要实现了这个接口,你就不需要做任何操作,Java会使用Reflection(反射技术)将类进行序列化和反序列化,非常的简单方便。但是有一个问题就是效率太低,在序列化和反序列化过程中会创建许多中间对象,会使得GC多次被调用,从而影响到程序的性能,我们都知道在GC被触发后进行垃圾回收的过程中,线程是被挂起的,APP会处于无响应状态,尽管这个过程持续的时间很短很短只有几十毫秒,但如果多次重复必定会影响到用户体验,一次Google的大牛们就不淡定了,这么差的性能怎么忍得了?但是如何破呢?答案就是Parcelable,他们造出了Parcelable来解决这个问题。

##Parcelable接口的使用
和上面一样,还是先来看看Parcelable接口是如何使用的。

lang: java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class ParcelableClass implements Parcelable{
String name;
int age;
float height;
List<Skill> skillList;

static final Parcelable.Creator<ParcelableClass> CREATOR
= new Parcelable.Creator<ParcelableClass>(){

@Overried
ParcelableClass createFromParcel(Parcel in){
return new ParcelableClass(in);
}

@Overried
ParcelableClass[] newArray(int size){
return new ParcelableClass[size];
}
}

ParcelableClass(Parcel in){
this.name = in.readString();
this.age = in.readInt();
this.height = in.readFloat();
this.skillList = new ArrayList<Skill>();
in.readTypedList(skillList,Skill.CREATOR);
}

@Overried
void writeToParcel(Parcel dest, int flags){
dest.writeString(this.name);
dest.writeInt(this.age);
dest.writeFloat(this.height);
dest.writeTypedList(this.skillList);
}

@Overried
int describeContents(){
return 0;
}

static class Skill implements Parcelable{
String skillName;
boolean gotIt;

static final Parcelable.Creator<Skill> CREATOR
= new Parcelable.Creator<Skill>(){

@Overried
Skill createFromParcel(Parcel in){
return new Skill(in);
}

@Overried
Skill[] newArray(int size){
return new Skill[size];
}
}

Skill(Parcel in){
this.skillName = in.readString();
this.gotIt = in.readBoolean();
}

@Overried
int describeContents(){
return 0;
}

@Overried
void writeToParcel(Parcel dest, int flags){
dest.writeString(skillName);
dest.writeBoolean(gotIt ? 1 : 0);
}
}

static class Skill implements Parcelable{
String skillName;
boolean gotIt;
}
}

终于写完了,这比刚才使用Serializable接口时的代码长了好几倍,代码的可读性也大不如刚刚的代码,但是为了性能上的提升,这么做也是值得的,与性能相比代码多点难点又算得了什么呢?何况这个代码也不是很难,而且是有迹可循的:

  1. 每个实现了Parcelable的接口都需要实现一个Parcelable.Creator对象。
  2. 提供一个以Parcel为参数的构造函数。
  3. 实现describeContents()方法
  4. 实现writeToParcel(Parcel dest, int flags)方法。

这样就OK了,下面来看看废了一番周折写出来的序列化方法到底比原生的好了多少,有图有真相!!
parcelable

OMG !这差距,使用Parcelable虽然复杂点,但是这性能提升,真是值了!

参考

Parcelable vs Serializable