Android系統中Parcelable和Serializable的區別

進行Android開發的時候,我們都知道不能將對象的引用傳給Activities或者Fragments,我們需要將這些對象放到一個Intent或者Bundle裏面,然後再傳遞。


通過Android的API,我們知道有兩種選擇,即在傳遞對象時,需要對我們的對象進行 Parcelable 或者Serializable化。作爲Java開發者,相信大家對Serializable 機制有一定了解,那爲什麼還需要 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, 速度至上


// 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


結果


wKioL1WCrZTxYUCwAAD5cZyKDsU745.jpg


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-serializable/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章