
導言
做Android開發(fā)的,相信大家都知道,Activity、Fragment之間的數(shù)據(jù)傳遞都是通過Bundle對象進行的。
而Bundle的Api中除了一些基本類型的方法之外,還有兩個特殊的方法:
/**
* Inserts a Parcelable value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
* @param key a String, or null
* @param value a Parcelable object, or null
*/
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
mFlags &= ~FLAG_HAS_FDS_KNOWN;
}
/**
* Inserts a Serializable value into the mapping of this Bundle, replacing
* any existing value for the given key. Either key or value may be null.
*
* @param key a String, or null
* @param value a Serializable object, or null
*/
@Override
public void putSerializable(@Nullable String key, @Nullable Serializable value) {
super.putSerializable(key, value);
}
那么,Serializable和Parcelable分別是什么呢?
Serializable
簡介
Serialization是java自帶的類型,做序列化用(把一個對象轉換為可存儲或可傳輸?shù)男问降倪^程),對象可以將其當前狀態(tài)存儲到本地、數(shù)據(jù)庫,也可以在網(wǎng)絡上傳輸。以后,可以從存儲區(qū)中讀取或反序列化對象的狀態(tài),重新創(chuàng)建該對象。
序列化的本質是將運行時的對象轉換為二進制流,保存到流、內存或通過網(wǎng)絡傳輸。
實現(xiàn)方式
對象序列化很簡單,只需要,實現(xiàn)Serialization類。
package com.bs.trade.main.bean;
import java.io.Serializable;
/**
* author : user_zf
* date : 18/3/17
* desc : 茶
*/
public class Tea implements Serializable {
private static final long serialVersionUID = -1241963366850216618L;
private String name;
private String price;
private String describe;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
}
看源碼可以發(fā)現(xiàn),Serialization是一個空的接口,它的作用是標志當前類可以被ObjectOutputStream序列化,和被ObjectInputStream反序列化。
可以看到需要定義一個serialVersionUID變量,這個變量類似于接口版本號,標志了唯一一個可序列化的類。序列化過程會保存serialVersionUID,反序列化過程會校驗版本號是否一致,如果不一致,會報InvalidClassException錯誤。
JVM規(guī)范強烈推薦手動聲明一個版本號,AndroidStudio中可以設置Lint提示,自動生成版本號。如果不手動設置這個值,系統(tǒng)會生成一個默認hash值,一旦類結構發(fā)生改變,hash值對應改變,那么反序列化就會校驗serialVersionUID失敗。設置了固定值,即使類結構發(fā)生改變,也能最大程度上保證反序列化成功率。不過如果類名改變,那么反序列化過程中會crash。
用法
public void put() {
Bundle bundle = new Bundle();
Tea tea = new Tea();
tea.setName("普洱");
tea.setPrice("13");
tea.setDescribe("清新可口,潤喉滋養(yǎng)");
bundle.putSerializable("TEA", tea);
}
public void get() {
Tea tea = (Tea) bundle.getSerializable("TEA");
}
Parcelable
簡介
Parcelable是Android專門提供類,實現(xiàn)的功能和Serialization一樣,就是把對象轉換為可存儲和可傳輸?shù)男问?。不過原理同Serialization不同,Parcelable是把一個完整的對象分進行分解,每一部分都是Intent和Bundle支持的類型。
實現(xiàn)方式
package com.bs.trade.main.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
* author : user_zf
* date : 18/3/17
* desc : 茶
*/
public class Tea implements Parcelable {
private String name;
private String price;
private String describe;
public Tea(){}
private Tea(Parcel source) {
name = source.readString();
price = source.readString();
describe = source.readString();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeString(price);
dest.writeString(describe);
}
public static final Creator<Tea> CREATOR = new Creator<Tea>() {
@Override
public Tea createFromParcel(Parcel source) {
return new Tea(source);
}
@Override
public Tea[] newArray(int size) {
return new Tea[size];
}
};
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getDescribe() {
return describe;
}
public void setDescribe(String describe) {
this.describe = describe;
}
}
要注意的是,字段讀取的順序和寫入的順序必須保持一致。
用法
public void put() {
Bundle bundle = new Bundle();
Tea tea = new Tea();
tea.setName("普洱");
tea.setPrice("13");
tea.setDescribe("清新可口,潤喉滋養(yǎng)");
bundle.putParcelable("TEA", tea);
}
public void get() {
Tea tea = bundle.getParcelable("TEA");
}
對比Serialization和Parcelable
- 在內存中使用的時候,Parcelable比Serialization性能高,推薦使用Parcelable,例如Activity、Fragment數(shù)據(jù)傳遞的場景
- Serialization會產(chǎn)生大量的臨時變量,從而引起頻繁的GC。
- Parcelable不能使用在將數(shù)據(jù)存儲在磁盤的情況(如SD卡,網(wǎng)絡傳輸),因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性,此時推薦使用Serialization。
寫于2018.03.17下午18:00(位置:深圳南山區(qū))