1、Parcelable和Serializable有什么用,它們有什么差別?.
Serializable是Java為我們提供的一個標準化的序列化接口,那什么是序列化呢? ---- 簡單來說就是將對象轉(zhuǎn)換為可以傳輸?shù)亩M制流(二進制序列)的過程,這樣我們就可以通過序列化,轉(zhuǎn)化為可以在網(wǎng)絡傳輸或者保存到本地的流(序列),從而進行傳輸數(shù)據(jù) ,那反序列化就是從二進制流(序列)轉(zhuǎn)化為對象的過程.
Serializable可以保存對象的屬性到本地文件、數(shù)據(jù)庫、網(wǎng)絡流、rmi以方便數(shù)據(jù)傳輸,當然這種傳輸可以是程序內(nèi)的也可以是兩個程序間的
Android的Parcelable的設計初衷是因為Serializable效率過慢,為了在程序內(nèi)不同組件間以及不同Android程序間(AIDL)高效的傳輸數(shù)據(jù)而設計,這些數(shù)據(jù)僅在內(nèi)存中存在,Parcelable是通過IBinder通信的消息的載體。
區(qū)別:
(1)性能上
Serializable : 序列化和反序列化都需要操作大量的IO,所以性能比較差
Parcelable : 不需要操作大量的IO,它基于Parcel提供了一套機制,可以將序列化之后的
數(shù)據(jù)寫入到一個共享內(nèi)存中,其他進程通過Parcel可以從這塊共享內(nèi)存中讀出字節(jié)流,并
反序列化成對象。號稱比Serializable性能快10倍的效率
(2)使用上
Serializable : 是Java提供的序列化接口,可以在任何java語言上使用,實現(xiàn)起來
比較簡單,實現(xiàn)Serializable接口即可.序列化機制依賴于一個Long類型serialVersionUID,
如果沒有顯示指定serialVersionUID 該值,系統(tǒng)基于該類計算一個值。如果類的結(jié)構(gòu)發(fā)生
變化就會導致自動計算的serialVersionUID 值不同。如果:序列化之后類如果新增一個字
段,反序列化過程就會失敗,一般會報java.io.InvalidClassException:
W/System.err: java.io.InvalidClassException: com.charles.plugin.gradledemo.parcelable.MyUserModel; Incompatible class (SUID):
com.charles.plugin.gradledemo.parcelable.MyUserModel: static final long
serialVersionUID =-2530467661280717770L; but expected
com.charles.plugin.gradledemo.parcelable.MyUserModel: static final long
serialVersionUID =2955893512855837466L;
而如果顯示指定了serialVersionUID,只要類結(jié)構(gòu)不發(fā)生重大變化,比如改類型或者字段
名。僅僅添加字段和刪除字段都能反序列成功.
Parcelable : 是 Android 提供的序列化接口,使用起來比較麻煩要實現(xiàn)describeContents()
和 writeToParcel() 放法,并且必須要有一個非空的靜態(tài)變量 CREATOR,我們提供一個
Parcelable.Creator<T>匿名內(nèi)部類,類似
public static final Creator<UserModel> CREATOR = new Creator<UserModel>() {
@Override
public UserModel createFromParcel(Parcel in) {
UserModel userModel = new UserModel();
userModel.setAge(in.readString());
userModel.setName(in.readString());
userModel.setSex(in.readString());
return userModel;
}
@Override
public UserModel[] newArray(int size) {
return new UserModel[size];
}
};
(3) 二者的選取規(guī)則
內(nèi)存序列化上選擇Parcelable, 存儲到設備或者網(wǎng)絡傳輸上選擇Serializable
(當然Parcelable也可以但是稍顯復雜)
2、自定義一個類讓其實現(xiàn)Parcelable,大致流程是什么?
(1)createFromParcel(Parcel in): 從序列化后的對象中創(chuàng)建原始對象
(2)newArray(int size):創(chuàng)建指定長度的原始對象數(shù)組
(3)writeToParcel:將當前對象寫入序列化結(jié)構(gòu)中。flags表示值0或1,為1時標示當前對象需要作為返回值返回,不能立即釋放資源。
(4)describeContents:返回當前對象的內(nèi)容描述,返回1時表示含有文件描述符。
public class UserModel implements Parcelable {
public static final Creator<UserModel> CREATOR = new Creator<UserModel>() {
@Override
public UserModel createFromParcel(Parcel in) {
UserModel userModel = new UserModel();
userModel.setAge(in.readString());
userModel.setName(in.readString());
userModel.setSex(in.readString());
return userModel;
}
@Override
public UserModel[] newArray(int size) {
return new UserModel[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
// 1.必須按成員變量聲明的順序封裝數(shù)據(jù),不然會出現(xiàn)獲取數(shù)據(jù)出錯
// 2.序列化對象
parcel.writeString(age);
parcel.writeString(name);
parcel.writeString(sex);
}
public UserModel(String name, String age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
private String name;
private String age;
private String sex;