Android 的序列化方式 Parcelable
Parcel 介紹:Parcel 內部包裝了可序列化的數據,可以在 Binder 中自由傳輸
Parcelable 是一個接口,只要實現這個接口,一個類的對象就可以實現序列化并可以通過 Intent 和 Binder 傳遞。
package com.renxl.touchevent.scrollview;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
private String name;
private int price;
private Category category;
protected Book(Parcel in) {
name = in.readString();
price = in.readInt();
category = in.readParcelable(Category.class.getClassLoader());
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
dest.writeParcelable(category, flags);
}
}
由上段代碼可以看出序列化過程需要實現的功能有 序列化,反序列化,內容描述 三部分
一、序列化功能
序列化功能是由 writeToParcel 方法完成的,是通過 Parcel 的一些了 write 方法完成的。
注意:序列化的類的成員屬性也必須是可序列化的。Parcel 的 writeParcelable 方法中除了可序列化的屬性,還需要添加 int 類型的 flag 參數,表示該對象應以何種方式寫入,一般傳 writeToParcel 方法的 flag 參數或者0。
二、反序列化功能
反序列化過程由 CREATOR 來完成,其內部表明了如何創建序列化對象和序列化對象的數組,創建序列化對象使用了序列化對象的參數為 Parcel 的構造方法,該方法中根據序列化過程得到的 Parcel 對象的 read 系列方法將序列化對象的內容還原完成反序列化過程。
如果序列化類的屬性有可序列化對象,在反序列化過程中需要傳遞當前線程的上下文類加載器,否則會報無法找到類的錯誤。
三、內容描述功能
內容描述功能由 describeContents 完成,幾乎所有情況該方法都返回 0 ,僅當當前對象中存在的文件描述符時此方法返回 1 。
文件描述符: 文件描述符在形式上是一個非負整數。實際上,它是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表。當程序打開一個現有文件或者創建一個新文件時,內核向進程返回一個文件描述符。在程序設計中,一些涉及底層的程序編寫往往會圍繞著文件描述符展開。但是文件描述符這一概念往往只適用于UNIX、Linux這樣的操作系統。
Android 系統提供的實現了 Parcelable 的類,Intent,Bundle,Bitmap等,List 和 Map 也可以序列化,前提是里面的內容都可以序列化。
序列化方式 Serializable 接口
Java 中提供的序列化方式,實現 Serializable 接口,是一個空接口,為對象提供了標準的序列化和反序列化操作。
只需要在類的聲明中指定 private static final long serialVersionUID = 123423432234L 即可,該值并不是必須的
serialVersionUID 作用為輔助序列化和反序列化過程,反序列化時序列化數據中的 serialVersionUID 和當前類的 serialVersionUID 相同是才能成功,不相同則會反序列化是吧,程序 crash。類中該值不指定時可以根據當前類的結構自動生成 hash ,不過當類結構變化時反序列化會失敗。如果指定,就算類的結構發生改變也會最大限度的恢復數據。
還有兩點點需要注意
- 靜態成員變量屬于類不屬于對象,所以不參與序列化過程,反序列化得到的對象也可以使用該屬性,但原理是因為使用的是類的靜態變量
- 被 transient 修飾的成員不參與序列化,反序列化后也不會得到 transient 修飾的成員
Parcelable 和 Serializable 區別
- 兩者都可以實現序列化并且都可以用于 Intent 間數據傳遞
- Serializable 是 Java 中的序列化接口,使用簡單但是開銷很大,序列化和反序列化過程需要很多 I/O 操作
- Parcelable 是 Android 中的序列化方式,更適合用在 Android 中,確定是使用麻煩,但是效率很高。Android 中首選 Parcelable
- Parcelable 主要用于 Android 跨進程通信時在對內存數據的序列話,跨進程傳輸的數據是必須序列化的,Parcelable 更方便
- 將對象序列化到設備的本地文件或者網絡傳輸,建議使用 Serializable,