parcelable與serializable都是序列化的操作,那麼我們先看 一下為何要使用序列化!
1)永久性儲存對象,儲存對象的位元組序列到本地檔案中;
2)通過序列化對象在網絡中傳遞對象;
3)通過序列化在程序間傳遞對象。
我們在項目中最經常遇到的情況就是,我們需要在activity或者service中傳遞對象,這個時候就需要用到序列化了!(需要在多個部件(Activity或Service)之間通過Intent傳遞一些資料,簡單類型(如:數字、字元串)的可以直接放入Intent。複雜類型必須實作Parcelable接口)
Android中實作序列化有兩個選擇:一是實作Serializable接口(是JavaSE本身就支援的),一是實作Parcelable接口(是Android特有功能,效率比實作Serializable接口高效,可用于Intent資料傳遞,也可以用于程序間通信(IPC))。實作Serializable接口非常簡單,聲明一下就可以了,而實作Parcelable接口稍微複雜一些,但效率更高,推薦用這種方法提高性能。
注:Android中Intent傳遞對象有兩種方法:一是Bundle.putSerializable(Key,Object),另一種是Bundle.putParcelable(Key,Object)。當然這些Object是有一定的條件的,前者是實作了Serializable接口,而後者是實作了Parcelable接口。
兩種序列化的差別是什麼呢?
1)在使用記憶體的時候,Parcelable比Serializable性能高,是以推薦使用Parcelable。
2)Serializable在序列化的時候會産生大量的臨時變量,進而引起頻繁的GC。
3)Parcelable不能使用在要将資料存儲在磁盤上的情況,因為Parcelable不能很好的保證資料的持續性在外界有變化的情況下。盡管Serializable效率低點,但此時還是建議使用Serializable 。
具體serializable與parcelable的使用差別呢
1)Serializable的實作,隻需要implements Serializable 即可。這隻是給對象打了一個标記,系統會自動将其序列化。
2)Parcelabel的實作,不僅需要implements Parcelabel,還需要在類中添加一個靜态成員變量CREATOR,這個變量需要實作 Parcelable.Creator 接口。
我們再來看一下parcelable的接口
public interface Parcelable
{
//内容描述接口,基本不用管
public int describeContents();
//寫入接口函數,打包
public void writeToParcel(Parcel dest, int flags);
//讀取接口,目的是要從Parcel中構造一個實作了Parcelable的類的執行個體處理。因為實作類在這裡還是不可知的,是以需要用到模闆的方式,繼承類名通過模闆參數傳入
//為了能夠實作模闆參數的傳入,這裡定義Creator嵌入接口,内含兩個接口函數分别傳回單個和多個繼承類執行個體
public interface Creator<T>
{
public T createFromParcel(Parcel source);
public T[] newArray(int size);
}
}
實作parcelablce的步驟是
1)implements Parcelable
2)重寫writeToParcel方法,将你的對象序列化為一個Parcel對象,即:将類的資料寫入外部提供的Parcel中,打包需要傳遞的資料到Parcel容器儲存,以便從 Parcel容器擷取資料
3)重寫describeContents方法,内容接口描述,預設傳回0就可以
4)執行個體化靜态内部對象CREATOR實作接口Parcelable.Creator
public static final Parcelable.Creator CREATOR
注:其中public static final一個都不能少,内部對象CREATOR的名稱也不能改變,必須全部大寫。需重寫本接口中的兩個方法:createFromParcel(Parcel in) 實作從Parcel容器中讀取傳遞資料值,封裝成Parcelable對象傳回邏輯層,newArray(int size) 建立一個類型為T,長度為size的數組,僅一句話即可(return new T[size]),供外部類反序列化本類數組使用。
簡而言之:通過writeToParcel将你的對象映射成Parcel對象,再通過createFromParcel将Parcel對象映射成你的對象。也可以将Parcel看成是一個流,通過writeToParcel把對象寫到流裡面,在通過createFromParcel從流裡讀取對象,隻不過這個過程需要你來實作,是以寫的順序和讀的順序必須一緻。