標籤:
本文轉自: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/
Android 序列化比對