Serializable、Parcelable詳解

Serializable

這是java提供的序列化接口,實現這個接口的類就能夠進行序列化了,所有的實現細節都是系統自動規定、完成的,序列化/反序列化實例如下:

// 序列化過程。方便查看邏輯,沒有添加try/catch
UserBean userBean = new UserBean("wk",15);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(new File(KuPathUtil.getImageDir(), "cache.txt")));
out.writeObject(userBean);
out.close();

// 反序列化
ObjectInputStream in = new ObjectInputStream(new FileInputStream(new File(KuPathUtil.getImageDir(), "525.txt")));
UserBean userBean = (UserBean) in.readObject();
in.close();

serialVersionUID是用來標識當前版本的,比如你的app在1.0版本的時候把UserBean對象序列化到rom中了,app升級到2.0後,UserBean類的結構發生了變化,此時再把rom中的文件反序列化成對象,肯定就會出錯了。

反序列化的時候會先檢查serialVersionUID是否一致,如果不一致就會報錯;如果id一致,但是類結構發生了輕微變化(比如增/刪了一兩個字段),也可以最大限度地反序列化,如果類結構發生了毀滅性的改變,就無法反序列化了;如果沒有serialVersionUID字段,理論上是無法反序列化的,但是用AS開發時,沒有id字段也可以反序列化,猜測是AS自動加的。

Parcelable

Serializable序列化和反序列化需要大量的I/O操作,開銷比較大,而很多時候我們只需要序列化一個對象,讓其作爲一個通信媒介。Parcelable就是Android專門提供的序列化接口,需要我們自己實現序列化和反序列化的接口。實際上,系統也提供了很多已經實現了Parcelable接口的類,比如Intent、Bundle、Bitmap等。

下面看一個標準的Parcelable接口實現:

public class UserBean implements Parcelable {
    private int mAge;
    private boolean isOld;
    private String mName;
    private Car mCar;
    private String[] mArray;
    private List<Car> mList;

    // 讀取序列化內容,轉換成該類對象
    private UserBean(Parcel in) {
        mAge = in.readInt();
        // 讀取Bool值
        isOld = in.readByte() != 0;
        mName = in.readString();
        // 讀取對象。需要用當前線程的上下文類加載器
        mCar = in.readParcelable(Thread.currentThread().getContextClassLoader());
        mArray = in.createStringArray();

        // 讀取List。需要List中的對象實現了Parcelable,參數list也不能爲空
        mList = new ArrayList<>();
        in.readTypedList(mList, Car.CREATOR);

    }

    // 反序列化
    public static final Parcelable.Creator<UserBean> CREATOR = new Parcelable.Creator<UserBean>() {
        @Override
        public UserBean[] newArray(int size) {
            // 序列化內容轉換成數組
            return new UserBean[size];
        }

        @Override
        public UserBean createFromParcel(Parcel source) {
            // 序列化內容轉換成對象
            return new UserBean(source);
        }
    };

    @Override
    public int describeContents() {
        // 在類UNIX系統中,一切皆是文件,文件描述符就是操作文件的數據結構,獲取到文件描述符可以完成所有文件相關的操作
        // 文件描述符的作用如此之大,爲了防止異常,需要禁止在Bundle傳輸Parcel時包含文件描述符,所以在Bundle中傳遞Parcelable數據時,該值必須返回0
        return 0;
    }

    @Override
    // 序列化。注意序列化和反序列化的順序一定要一致
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(mAge);
        dest.writeByte((byte) (isOld ? 1 : 0));
        dest.writeString(mName);
        dest.writeParcelable(mCar, flags);
        dest.writeStringArray(mArray);
        dest.writeTypedList(mList);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章