什麼是序列化?Serializable接口和Parcelable接口的區別?

所謂的序列化指的是把對象轉換成字節序列的過程,也能夠稱之爲對象流,能夠保存到文件中,也能夠用來網絡傳輸數據。java

反序列化既是相反的過程,能夠從咱們的文件中把對象流(字節序列)讀出來,轉換爲對象供咱們使用。數組

序列化的實現步驟以下:網絡

a)Make a FileOutputStream
java 代碼
FileOutputStream fs = new FileOutputStream("foo.ser");
b)Make a ObjectOutputStream
java 代碼
ObjectOutputStream os = new ObjectOutputStream(fs);
c)write the object
java 代碼
os.writeObject(myObject1); 
os.writeObject(myObject2); 
os.writeObject(myObject3);
d) close the ObjectOutputStream
java 代碼
os.close();

反之能夠這樣作:性能

a)Make a FileInputStream
java 代碼
FileInputStream fs = new FileInputStream("foo.ser");
b)Make a ObjectInputStream
java 代碼
ObjectInputStream os = new ObjectInputStream(fs);
c)write the object
java 代碼
os.readObject(myObject1);
os.readObject(myObject2);
os.readObject(myObject3);
d) close the ObjectInputStream
java 代碼
os.close();

若是想要轉換成字符串存儲起來能夠這樣來作:spa

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
    objectOutputStream.writeObject(bean);
    serStr = byteArrayOutputStream.toString("ISO-8859-1");
    serStr = java.net.URLEncoder.encode(serStr, "UTF-8");
    objectOutputStream.close();
    byteArrayOutputStream.close();
} catch (IOException e) {
    e.printStackTrace();
}

反之能夠這樣作來取出已經序列化的數據:.net

try {
    String redStr = java.net.URLDecoder.decode(strBean, "UTF-8");
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(redStr.getBytes("ISO-8859-1"));
    ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
    bean = (PFUserBean) objectInputStream.readObject();
    objectInputStream.close();
    byteArrayInputStream.close();
} catch (Exception e) {
    e.printStackTrace();
}

Serializable接口和Parcelable接口有什麼區別呢?code

首先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 。

應用場景

須要在多個部件(Activity或Service)之間經過Intent傳遞一些數據,簡單類型(如:數字、字符串)的能夠直接放入Intent。複雜類型必須實現Parcelable接口。

Parcelable實現步驟

1)implements Parcelable

2)重寫writeToParcel方法,將你的對象序列化爲一個Parcel對象,即:將類的數據寫入外部提供的Parcel中,打包須要傳遞的數據到Parcel容器保存,以便從 Parcel容器獲取數據

3)重寫describeContents方法,內容接口描述,默認返回0就能夠

4)實例化靜態內部對象CREATOR實現接口Parcelable.Creator

public static final Parcelable.Creator<T> 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從流裏讀取對象,只不過這個過程須要你來實現,所以寫的順序和讀的順序必須一致。

舉個栗子

public class MyParcelable implements Parcelable {
    private int mData;

    //這裏直接return 0便可
    public int describeContents() {
        return 0;
    }

    //將該類的屬性寫入對象流中
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mData);
    }

    public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() {
        public MyParcelable createFromParcel(Parcel in) {
            return new MyParcelable(in);
        }

        public MyParcelable[] newArray(int size) {
            return new MyParcelable[size];
        }
    };

    //從對象流中讀出屬性
    private MyParcelable(Parcel in) {
        mData = in.readInt();
    }
}

綜上所述,仍是建議使用Parcelable 來進行對象的序列化支持。

相關文章
相關標籤/搜索