本文转自:https://www.zybuluo.com/linux1s1s/note/91046
注:部分内容有更改
在Android中使用序列化,无非两种途经: Parcelable
和 Serializable
两者区别
- Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。
- Parcelable的设计初衷是因为Serializable效率过慢,为了在程序内不同组件间以及不同Android程序间(AIDL)高效的传输数据而设计,这些数据仅在内存中存在,Parcelable是通过IBinder通信的消息的载体。如果想进一步了解进程间通信AIDL方式可以看博文:Android 进程间通信IPC_AIDL
- Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如activity间传输数据
- Serializable可将数据持久化方便保存,所以在需要保存或网络传输数据时选择Serializable,因为android不同版本Parcelable可能不同,所以不推荐使用Parcelable进行数据持久化
Serializable
public class SerializableDeveloper implements Serializable String name; int yearsOfExperience; List<Skill> skillSet; float favoriteFloat; static class Skill implements Serializable { String name; boolean programmingRelated; } }
serializable的迷人之处在于你只需要对某个类以及它的属性实现Serializable 接口即可。Serializable 接口是一种标识接口(marker interface),这意味着无需实现方法,Java便会对这个对象进行高效的序列化操作。
这种方法的缺点是使用了反射,序列化的过程较慢。这种机制会在序列化的时候创建许多的临时对象,容易触发垃圾回收。
Parcelable
public class Video implements Parcelable { private long id; private String picture; private String title; private String author; private String duration; private String uploadTime; public Video() { } public Video(Parcel input) { id = input.readLong(); picture = input.readString(); title = input.readString(); author = input.readString(); duration = input.readString(); uploadTime = input.readString(); } public Video(long id, String picture, String title, String author, String duration, String uploadTime) { this.author = author; this.duration = duration; this.id = id; this.picture = picture; this.title = title; this.uploadTime = uploadTime; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getDuration() { return duration; } public void setDuration(String duration) { this.duration = duration; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getPicture() { return picture; } public void setPicture(String picture) { this.picture = picture; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getUploadTime() { return uploadTime; } public void setUploadTime(String uploadTime) { this.uploadTime = uploadTime; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(id); dest.writeString(picture); dest.writeString(title); dest.writeString(author); dest.writeString(duration); dest.writeString(uploadTime); } public static final Parcelable.Creator<Video> CREATOR = new Parcelable.Creator<Video>() { @Override public Video createFromParcel(Parcel source) { return new Video(source); } @Override public Video[] newArray(int size) { return new Video[size]; } }; }
根据 google 工程师的说法,这些代码将会运行地特别快。原因之一就是我们已经清楚地知道了序列化的过程,而不需要使用反射来推断。同时为了更快地进行序列化,对象的代码也需要高度优化。
因此,很明显实现Parcelable并不容易。实现Parcelable接口需要写大量的模板代码,这使得对象代码变得难以阅读和维护。
性能测试
通过将一个对象放到一个bundle里面然后调用Bundle#writeToParcel(Parcel, int)方法来模拟传递对象给一个activity的过程,然后再把这个对象取出来,在一个循环里面运行1000 次。
小结
如果你想成为一个优秀的软件工程师,你需要多花点时间来实现 Parcelable ,因为这将会为你对象的序列化过程快10多倍,而且占用较少的资源。
但是大多数情况下, Serializable 的龟速不会太引人注目。你想偷点懒就用它吧,不过要记得serialization是一个比较耗资源的操作,尽量少使用。
如果你想要传递一个包含许多对象的列表,那么整个序列化的过程的时间开销可能会超过一秒,这会让屏幕转向的时候变得很卡顿
另外有一种说法是:在Activity之间传递数据使用Serializable在某种情况下会失败,这样的案例尚未遇到过。(个人猜测:难道是持久化数据需要写入扩展SD卡,如果一旦出现写入或者读取失败,那么传输就会失败)
本文翻译和整理自:http://www.developerphil.com/parcelable-vs-serializable/