一、序列化是什么:
序列化是指把Java對(duì)象轉(zhuǎn)換為字節(jié)序列并存儲(chǔ)到一個(gè)存儲(chǔ)媒介的過(guò)程。反之色冀,把字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程則稱之為反序列化。
二柱嫌、為什么要序列化:
Java對(duì)象存在的一個(gè)前提是JVM有在運(yùn)行锋恬,因此,如果JVM沒有運(yùn)行或者在其他機(jī)器的JVM上是不可能獲取到指定的Java對(duì)象的编丘。而序列化操作則是把Java對(duì)象信息保存到存儲(chǔ)媒介与学,可以在以上不可能的情況下仍然可以使用Java對(duì)象。
三嘉抓、序列化的主要作用:
永久性保存對(duì)象索守,保存對(duì)象的字節(jié)序列到本地文件中;
通過(guò)序列化對(duì)象在網(wǎng)絡(luò)中傳遞對(duì)象抑片;
通過(guò)序列化在進(jìn)程間傳遞對(duì)象卵佛。
四、Android中序列化:
在Android開發(fā)中敞斋,經(jīng)常需要在多個(gè)部件(Activity截汪、Fragment或Service)之間通過(guò)Intent傳遞一些數(shù)據(jù),如果是一些普通類型的數(shù)據(jù)可以通過(guò)PutExtra()進(jìn)行傳遞植捎,如果是對(duì)象的話就得先進(jìn)行序列化才能傳遞了衙解。在Android中有兩種序列化的接口,Serializable和Parcelable焰枢。
Serializable:(JavaSE本身就支持的)保存對(duì)象的屬性到本地文件蚓峦、數(shù)據(jù)庫(kù)、網(wǎng)絡(luò)流医咨、rmi以方便數(shù)據(jù)傳輸枫匾。
Parcelable:(Android特有功能)因?yàn)镾erializable效率過(guò)慢架诞,為了在程序內(nèi)不同組件間以及不同Android程序間(AIDL)高效
的傳輸數(shù)據(jù)而設(shè)計(jì)拟淮,這些數(shù)據(jù)僅在內(nèi)存中存在。
五谴忧、Parcelable和Serializable的比較:
區(qū)別 | Serializable | Parcelable |
---|---|---|
所屬API | JAVA API | Android SDK API |
原理 | 序列化和反序列化過(guò)程需要大量的I/O操作 | 序列化和反序列化過(guò)程不需要大量的I/O操作 |
開銷 | 開銷大 | 開銷小 |
效率 | 低 | 很高 |
使用場(chǎng)景 | 序列化到本地或者通過(guò)網(wǎng)絡(luò)傳輸 | 內(nèi)存序列化 |
1)在使用內(nèi)存的時(shí)候很泊,Parcelable比Serializable性能高,所以推薦使用Parcelable沾谓。
2)Serializable在序列化的時(shí)候會(huì)產(chǎn)生大量的臨時(shí)變量委造,從而引起頻繁的GC。
3)Parcelable不能使用在要將數(shù)據(jù)存儲(chǔ)在磁盤上的情況均驶,因?yàn)镻arcelable不能很好的保證數(shù)據(jù)的持續(xù)性在外界有變化的情況下昏兆。盡管Serializable效率低點(diǎn),但此時(shí)還是建議使用Serializable 妇穴。
對(duì)于使用序列化還有兩點(diǎn)需要了解:
1.靜態(tài)成員變量屬于類不屬于對(duì)象爬虱,所以不參與序列化過(guò)程
2.用transient關(guān)鍵字標(biāo)記的成員變量不參與序列化過(guò)程
六隶债、兩種序列化方式的實(shí)現(xiàn):
Serializable接口的實(shí)現(xiàn)
只需要實(shí)現(xiàn)Serializable接口,并提供一個(gè)序列化版本id(serialVersionUID)即可跑筝。
public class DataBean implements Serializable{
...
}
Parcelable接口的使用
Parcelable實(shí)現(xiàn)方式略復(fù)雜一些死讹,需重寫describeContents和writeToParcel這兩個(gè)方法提供一個(gè)名為CREATOR常量。實(shí)際上就是將如何打包和解包的工作自己來(lái)定義曲梗,
而序列化的這些操作完全由底層實(shí)現(xiàn)赞警。
public class DataBean implements Parcelable{
private int id;
private String name;
private String Account;
private int kind;
private String password;
private String desc;
public DataBean(){}
// 用來(lái)創(chuàng)建自定義的Parcelable的對(duì)象
public static final Creator<DataBean> CREATOR = new Creator<DataBean>() {
@Override
public DataBean createFromParcel(Parcel in) {
return new DataBean(in);
}
@Override
public DataBean[] newArray(int size) {
return new DataBean[size];
}
};
//GET SET方法
...
@Override
public String toString() {
return "DataBean{" +
"id=" + id +
", name='" + name + '\'' +
", Account='" + Account + '\'' +
", kind=" + kind +
", password='" + password + '\'' +
", desc='" + desc + '\'' +
'}';
}
@Override
public int describeContents() {
return 0;
}
// 寫數(shù)據(jù)進(jìn)行保存
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.id);
dest.writeString(this.Account);
dest.writeString(this.name);
dest.writeString(this.password);
dest.writeInt(this.kind);
dest.writeString(this.desc);
}
// 讀數(shù)據(jù)進(jìn)行恢復(fù)
protected DataBean(Parcel in) {
this.id = in.readInt();
this.kind = in.readInt();
this.password = in.readString();
this.name = in.readString();
this.Account = in.readString();
this.desc = in.readString();
}
}
這樣就完成了對(duì)DataBean的序列化,使用的時(shí)候就可以通過(guò)Intent進(jìn)行傳遞了虏两。
//Activity傳遞對(duì)象,不管是實(shí)現(xiàn)哪個(gè)接口都是用如下方式傳遞
intent.putExtra("data",data);
//在另一個(gè)Activity中接收對(duì)象的方式分別是:
DataBean data = getIntent().getSerializableExtra("data");
DataBean data = getIntent().getParcelableExtra("data");