進行Android開發的時候,咱們都知道不能將對象的引用傳給Activities或者Fragments,咱們須要將這些對象放到一個Intent或者Bundle裏面,而後再傳遞。android
經過Android的API,咱們知道有兩種選擇,即在傳遞對象時,須要對咱們的對象進行 Parcelable 或者Serializable化。做爲Java開發者,相信你們對Serializable 機制有必定了解,那爲何還須要 Parcelable呢?ide
爲了回答這個問題,讓咱們分別來看看這二者的差別。post
Serializable, 簡單易用性能
public class SerializableDeveloper implements Serializable測試
String name;優化
int yearsOfExperience;this
List<Skill> skillSet;google
float favoriteFloat;對象
static class Skill implements Serializable {接口
String name;
boolean programmingRelated;
}
}
serializable的迷人之處在於你只須要對某個類以及它的屬性實現Serializable 接口便可。Serializable 接口是一種標識接口(marker interface),這意味着無需實現方法,Java便會對這個對象進行高效的序列化操做。
這種方法的缺點是使用了反射,序列化的過程較慢。這種機制會在序列化的時候建立許多的臨時對象,容易觸發垃圾回收。
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接口須要寫大量的模板代碼,這使得對象代碼變得難以閱讀和維護。
速度測試
固然,咱們仍是想知道到底Parcelable相對於Serializable要快多少。
測試方法
經過將一個對象放到一個bundle裏面而後調用Bundle#writeToParcel(Parcel, int)方法來模擬傳遞對象給一個activity的過程,而後再把這個對象取出來。
在一個循環裏面運行1000 次。
兩種方法分別運行10次來減小內存整理,cpu被其餘應用佔用等狀況的干擾。
參與測試的對象就是上面代碼中的SerializableDeveloper 和 ParcelableDeveloper。
在多種Android軟硬件環境上進行測試
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.16倍。
NEXUS 4
Serializable: 1.8539ms – Parcelable: 0.1824ms – 提高11.80倍。
DESIRE Z
Serializable: 5.1224ms – Parcelable: 0.2938ms – 提高17.36倍。
由此能夠得出: Parcelable 比 Serializable快了10多倍。有趣的是,即便在Nexus 10這樣性能強悍的硬件上,一個至關簡單的對象的序列化和反序列化的過程要花將近一毫秒。
總結
若是你想成爲一個優秀的軟件工程師,你須要多花點時間來實現 Parcelable ,由於這將會爲你對象的序列化過程快10多倍,並且佔用較少的資源。
可是大多數狀況下, Serializable 的龜速不會太引人注目。你想偷點懶就用它吧,不過要記得serialization是一個比較耗資源的操做,儘可能少使用。
若是你想要傳遞一個包含許多對象的列表,那麼整個序列化的過程的時間開銷可能會超過一秒,這會讓屏幕轉向的時候變得很卡頓。
英文原文:developerphil
譯文來源:Android Cool Posts
連接:http://greenrobot.me/devpost/android-parcelable-serializ