###Parcelable vs Serializable
在一开始学习Android的时候,我们就知道了不能在Activity和Fragment之间直接传递对象,必须使用Intent或者Bundle。 查看api后,我们发现有两个选择,让我们的对象要么实现Parcelable,要么实现Serializable。作为Java开发者,我们都知道Serializable机制,那么为什么还需要Parcelable呢? 要接解答这个问题,先来看两个列子
####Serializable-简洁之至
// access modifiers, accessors and constructors omitted for brevity
public class SerializableDeveloper implements Serializable
String name;
int yearsOfExperience;
List<Skill> skillSet;
float favoriteFloat;
static class Skill implements Serializable {
String name;
boolean programmingRelated;
}
}
正如你所见到的,只需要在类和成员变量引用类实现Serializable接口就可以了,并且不需要实现任何方法。其他的事情统统交给Java去做,简洁之至。 但是Serializable的问题就是处理太慢,Java是采用反射去实现序列号操作。并且在处理序列化的时候还会生成大量的对象,导致GC频繁发生。
####Parcelable-速度之王
// access modifiers, accessors and regular constructors ommited for brevity
class ParcelableDeveloper implements Parcelable {
String name;
int yearsOfExperience;
List<Skill> skillSet;
float favoriteFloat;
ParcelableDeveloper(Parcel in) {
this.name = in.readString();
this.yearsOfExperience = in.readInt();
this.skillSet = new ArrayList<Skill>();
in.readTypedList(skillSet, Skill.CREATOR);
this.favoriteFloat = in.readFloat();
}
void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(yearsOfExperience);
dest.writeTypedList(skillSet);
dest.writeFloat(favoriteFloat);
}
int describeContents() {
return 0;
}
static final Parcelable.Creator<ParcelableDeveloper> CREATOR
= new Parcelable.Creator<ParcelableDeveloper>() {
ParcelableDeveloper createFromParcel(Parcel in) {
return new ParcelableDeveloper(in);
}
ParcelableDeveloper[] newArray(int size) {
return new ParcelableDeveloper[size];
}
};
static class Skill implements Parcelable {
String name;
boolean programmingRelated;
Skill(Parcel in) {
this.name = in.readString();
this.programmingRelated = (in.readInt() == 1);
}
@Override
void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(programmingRelated ? 1 : 0);
}
static final Parcelable.Creator<Skill> CREATOR
= new Parcelable.Creator<Skill>() {
Skill createFromParcel(Parcel in) {
return new Skill(in);
}
Skill[] newArray(int size) {
return new Skill[size];
}
};
@Override
int describeContents() {
return 0;
}
}
}
根据google开发人员所说,这段代码执行速度会有明显的提升。其中一个原因是,我们正在明确有关序列化过程,而不是使用反射来推断它。这里也可以看到,代码为实现这个目的做了大量的优化。 然而Parcelable也不是免费的,它需要按规则编写大量的代码模板去实现序列化过程,并且难以阅读。
####性能测试
那么问题来了,Parcelable究竟有多快?
#####测试步骤
- 在Activity中使用Bundle#writeToParcel(Parcel, int)方法将一个对象写入,然后再取出来来模仿对象传递的过程。
- 重复运行1000次
- 取10次平均值,为了反映不同内存使用,其他app不同cpu消耗等情况
- 使用上面的SerializableDeveloper和ParcelableDeveloper进行测试
- 在不同手机不行版本下运行 + LG Nexus 4 - Android 4.2.2 + Samsung Nexus 10 - Android 4.2.2 + HTC Desire Z - Android 2.3.3
#####测试结果
Nexus 10 Serializable: 1.0004ms, Parcelable: 0.0850ms - 10.16x 提升. Nexus 4 Serializable: 1.8539ms - Parcelable: 0.1824ms - 11.80x 提升. Desire Z Serializable: 5.1224ms - Parcelable: 0.2938ms - 17.36x 提升.
结果就是这样,Parcelable至少比Serializable快10倍。而且还可以看到,即使在Nexus 10上,一个相对简单对象做一次完整的serialize/deserialize也需要1毫秒。
####结论
如果你想做一个优秀的开发者,请尽量使用Parcelable。因为Parcelable至少会快10倍而且占用更少的内存。 在大多数情况下,缓慢的Serializable也不会被特别注意到。用它也不会有多大关系,但是请记住,它是一个昂贵的操作。 如果你试着传递数以千计的Serializable对象数组或列表,处理整个过程可能需要花费超过一秒的时间。就会导致页面跳转或者横竖屏切换呆滞。
####后记
如果你看到了这里,我就会给你免费赠送一个大礼包! 手动写Parcelable实在是太麻烦了,而且大部分都是复制黏贴改动。网上的工具类原理也是使用apt生成代码,然后反射执行,对效率还是稍稍有点影响。 幸运的是,现在AndroidStudio已经有了辅助插件——Android Parcelable Code Generator。使用这款插件可以方便的自动生成Parcelable代码。
安装方法:
- 下载安装包
- 打开IntelliJ或者Android Studio
- Settings -> Preferences -> Plugins -> Install plugin from disk....
- 选择下载的安装包
在win中按下alt+Insert,mac按下command+N。效果如下:
参考资料 http://www.developerphil.com/parcelable-vs-serializable/ https://plugins.jetbrains.com/plugin/7332?pr=androidstudio https://github.com/mcharmas/android-parcelable-intellij-plugin
来源:oschina
链接:https://my.oschina.net/u/724985/blog/416488