安卓序列化有兩種方式,分別是實現Serializable接口和Parcelable接口,其中Serializable接口是來自Java中的序列化接口,而Parcelable是Android自帶的序列化接口。
上述的兩種序列化接口都有各自不同的優缺點,我們在實際使用時需根據不同情況而定。
1.Serializable在序列化的時候會產生大量的臨時變量,從而引起頻繁的GC,而相比之下Parcelable的性能更高(畢竟是Android自帶的),所以當在使用內存時(如:序列化對象在網絡中傳遞對象或序列化在進程間傳遞對象),更推薦使用Parcelable接口。
2.但Parcelable有個明顯的缺點:不能能使用在要將數據存儲在磁盤上的情況(如:永久性保存對象,保存對象的字節序列到本地文件中),因爲Parcel本質上爲了更好的實現對象在IPC間傳遞,並不是一個通用的序列化機制,當改變任何Parcel中數據的底層實現都可能導致之前的數據不可讀取,所以此時還是建議使用Serializable 。
Serializable接口的實現及使用:
Serializable的接口實現很簡單,只需讓需要序列化的類繼承Serializable 即可,系統會自動將其序列化,具體代碼如下:
public
class
Book
implements
Serializable {
private
static
final
long
serialVersionUID = 21455356667888L;//記得這裏要填上
private
String mName;
private
int
mPrice;
private boolean flag;
那麼在intent傳遞的時候,代碼如下:
Book book =
new
Book();
book.setmName(
"王海康"
);
book.setmPrice(
"20$"
);
Intent intent =
new
Intent(
this
, BookTest.
class
);
Bundle bundle =
new
Bundle();
bundle.putSerializable(SER_KEY, book);
intent.putExtras(bundle);
startActivity(intent);
Book mBook = (Book )getIntent().getSerializableExtra(SER_KEY);
Parcelable接口的實現及使用
實現Parcelable接口主要可以分爲一下幾步:
1)implements Parcelable。
2)重寫writeToParcel方法,將你的對象序列化爲一個Parcel對象,即:將類的數據寫入外部提供的Parcel中,打包需要傳遞的數據到Parcel容器保存,以便從Parcel容器獲取數據。
3)重寫describeContents方法,內容接口描述,默認返回0即可。
4)實例化靜態內部對象CREATOR實現接口Parcelable.Creator 。
注意:若將Parcel看成是一個流,則先通過writeToParcel把對象寫到流裏面,再通過createFromParcel從流裏讀取對象,因此類實現的寫入順序和讀出順序必須一致。
具體實現代碼如下:
public
class
Person
implements
Parcelable {
public String name; public int money; public boolean flag;
@Override
public
int
describeContents() {
return
0
;
}
@Override
public
void
writeToParcel(Parcel dest,
int
flags) {
dest.writeString(name); dest.writeInt(money); dest.writeByte((byte)(flag ? 1:0));//if myBoolean == true, byte == 1
}
public
static
final
Parcelable.Creator<Person> CREATOR =
new
Creator<Person>() {
@Override
public
Person createFromParcel(Parcel source) {
//這裏一定要注意,這裏的順序一定要不要搞錯了.不然取不出來值,爲這個我頭痛了二個小時 //如果有boolean類型的數據,在這裏就得傳爲數值型,然後再轉回去 Personperson
= new Person();person
.name = source.readString();person
.money = source.readInt();person
.flag = source.readByte() != 0; //myBoolean == true if byte != 0
return
person;
}
//供反序列化本類數組時調用的
@Override
public
Person[] newArray(
int
size) {
return
new
Person[size];
}
};
然後關於parcel方式的數據傳遞和接受,其實和上面介紹的Serial方式是差不多的,就不介紹了。
2)下面介紹下如何傳遞一個列表對象(List<Person>):前提是集合中的對象必須實現了Parcel規則
// parcelable對象List傳遞方法
public void setParcelableListMethod() {
ArrayList<Person> personList = new ArrayList<Person>();
Person person1 = new Person();
person1.setmName("王海康");
person1.setmSex("男");
person1.setmAge(45);
personList.add(person1);
Person person2 = new Person();
person2.setmName("薛嶽");
person2.setmSex("男");
person2.setmAge(15);
personList.add(person2);
Intent intent = new Intent(this, PersonTest.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList(PAR_LIST_KEY, personList);
intent.putExtras(bundle);
startActivity(intent);
}
// parcelable對象獲取方法
public ArrayList<Person> getParcelableMethod(){
ArrayList<Person> mPersonList = getIntent().getParcelableExtra(PAR_LIST_KEY);
return mPersonList;
}
3)最後介紹一個投機取巧的方法:
不用繼承Parcelable或Serializable方法即可實現IPC中對象的傳遞。這種方法的實現原理不是很明白,只知道代碼中new ArrayList()返回的其實是一個EmptyArray.OBJECT數組,不過我感覺應該還是系統調用Serializable進行序列化的。
//對象List傳遞
public
void
setObjectMethod(){
......(省略)
ArrayList list =
new
ArrayList();
//ObjectList爲某一對象列表
list.add(ObjectList);
bundle.putParcelableArrayList(PAR_LIST_KEY, list);
intent.putExtras(bundle);
startActivity(intent);
}
//獲取對象List
ArrayList list = bundle.getParcelableArrayList(
"list"
);
//強轉成你自己定義的list,這樣ObjectList就是你傳過來的那個list了。
ObjectList= (List<Object>) list.get(
0
);