一蛮瞄、作用
兩者都是用于對象的序列化成二進(jìn)制的流棍郎,便于在intent或bundle中傳輸钦讳。
二阅签、區(qū)別
1. Serializable
Serializable是java的序列化接口掐暮,核心實現(xiàn)是ObjectOutPutStream.writeObject()
進(jìn)行序列化,ObjectInputStream.readObject()
進(jìn)行反序列化政钟。
serialVersionUID
可在序列化的類中定義serialVersionUID
路克,用static和final修飾化漆,用于在反序列化中驗證類版本的差異核行。
- 如果不定義serialVersionUID,系統(tǒng)會聲明個默認(rèn)值柜候,當(dāng)類發(fā)生變化后碎连,serialVersionUID將會被系統(tǒng)重新計算賦值灰羽,反序列化時,如果前后serialVersionUID不一致鱼辙,將會crash廉嚼,拋出
InvalidClassException
錯誤。 - 如果定義serialVersionUID座每,盡管序列化后類發(fā)生變化前鹅,由于前后serialVersionUID一致,反序列化時也會盡最大的程度復(fù)原峭梳,如果復(fù)原失敗一樣會拋出
InvalidClassException
錯誤舰绘。
在Android Serializable 的Api注釋中有段說明:針對Android N以上版本的設(shè)備時,為了保證對之前版本的兼容性葱椭,強(qiáng)烈建議顯示的定義serialVersionUID捂寿,而不是由系統(tǒng)默認(rèn)賦值。
2. Parcelable
Parcelable是Android特有的序列化接口孵运,核心實現(xiàn)是通過parcel的讀寫操作進(jìn)行序列化秦陋,里面的方法是Native方法。
- 使用Serializable會頻繁進(jìn)行IO操作治笨,開銷很大驳概,在Android平臺上,Parcelable多用于內(nèi)存序列化旷赖,如IPC進(jìn)程間通信顺又。
三、實現(xiàn)Parcelable步驟
public class Student implements Parcelable {
private int id;
private String name;
private boolean isBoy;
private Student(Parcel in) {
id = in.readInt();
name = in.readString();
isBoy = in.readByte() != 0;
}
public static final Creator<Student> CREATOR = new Creator<Student>() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(name);
parcel.writeByte((byte) (isBoy ? 1 : 0));
}
}
實現(xiàn)Parcelable必須實現(xiàn)describeContents()
和writeToParcel(Parcel parcel, int i)
方法等孵。還需要創(chuàng)建個Parcelable.Creator
接口的成員稚照,用于進(jìn)行反序列化操作。
3.1 describeContents()
方法返回當(dāng)前對象的內(nèi)容描述,如果含有文件描述符果录,則返回1上枕,一般默認(rèn)返回0。
/**
* Describe the kinds of special objects contained in this Parcelable
* instance's marshaled representation. For example, if the object will
* include a file descriptor in the output of {@link #writeToParcel(Parcel, int)},
* the return value of this method must include the
* {@link #CONTENTS_FILE_DESCRIPTOR} bit.
*
* @return a bitmask indicating the set of special object types marshaled
* by this Parcelable object instance.
*/
public @ContentsFlags int describeContents();
3.2 writeToParcel(Parcel, int)
在這方法進(jìn)行序列化弱恒,falg默認(rèn)為0辨萍;如果需要對象作為返回值返回,則值為1斤彼,這樣不能立即釋放資源分瘦。
/**
* Flatten this object in to a Parcel.
*
* @param dest The Parcel in which the object should be written.
* @param flags Additional flags about how the object should be written.
* May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}.
*/
public void writeToParcel(Parcel dest, @WriteFlags int flags);
3.3 Parcelable.Creator
/**
* Interface that must be implemented and provided as a public CREATOR
* field that generates instances of your Parcelable class from a Parcel.
*/
public interface Creator<T> {
/**
* Create a new instance of the Parcelable class, instantiating it
* from the given Parcel whose data had previously been written by
* {@link Parcelable#writeToParcel Parcelable.writeToParcel()}.
*
* @param source The Parcel to read the object's data from.
* @return Returns a new instance of the Parcelable class.
*/
public T createFromParcel(Parcel source);
/**
* Create a new array of the Parcelable class.
*
* @param size Size of the array.
* @return Returns an array of the Parcelable class, with every entry
* initialized to null.
*/
public T[] newArray(int size);
}
createFromParcel ()
:反序列化,創(chuàng)建原始序列化對象
newArray ()
:反序列化琉苇,創(chuàng)建原始序列化對象的數(shù)組
內(nèi)部通過Parcel的read方法實現(xiàn)嘲玫。
成員也需實現(xiàn)Parcelable才能保證序列化的完整
如果Student不實現(xiàn)Parcelable,那么School實現(xiàn)序列化的成員不包括Student
public class School implements Parcelable {
private String name;
private Student student;
private School(Parcel in) {
name = in.readString();
student = in.readParcelable(Student.class.getClassLoader());
}
public static final Creator<School> CREATOR = new Creator<School>() {
@Override
public School createFromParcel(Parcel in) {
return new School(in);
}
@Override
public School[] newArray(int size) {
return new School[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeParcelable(student, i);
}
}
student = in.readParcelable(Student.class.getClassLoader())
在反序列化時并扇,需要獲取當(dāng)前線程的成員類的加載器去团,否則會報找不到該類的錯誤。