轉(zhuǎn)載請說明出處: Android AIDL基礎(chǔ) -- Parcelable接口
什么是Parcelable接口
作用:給類設(shè)計的接口,類一旦實現(xiàn)這個接口骂澄,該類的對象即可進行一個“從對象存儲為Parcel , 從Parcel讀取為對象”的一個讀寫過程惕虑。
目的:實現(xiàn)序列化
原因:
序列化坟冲,為了:
1) 永久保存對象,保存對象的字節(jié)到本地文件中
2) 通過序列化對象在網(wǎng)絡(luò)中傳遞對象
3) 通過序列化在進程間傳遞對象-
與Serializable對比:
1)在使用Intent傳遞數(shù)據(jù)時:- Serializable: Bundle.putSerializable(Key, 實現(xiàn)了Serializable的對象);
- Parcelable: Bundle.putParcelable(Key, 實現(xiàn)了Parcelable的對象);
2)內(nèi)存使用性能上:
- Parcelable > Serializable
由于Serializable在序列化時會產(chǎn)生大量的臨時變量溃蔫,從而引起頻繁的GC樱衷。
3)數(shù)據(jù)存儲在磁盤上的情況:
- Serialzable > Parcelable
Parcelable不能使用在要將數(shù)據(jù)存儲在磁盤上的情況,因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性在外界有變化的情況下酒唉。盡管Serializable效率低點,但此時還是建議使用Serializable
-
支持的成員數(shù)據(jù)類型:
1) 普通數(shù)據(jù)類型【如:int沸移、double等以及他們的封裝類如Integer痪伦、Float等】以及他們的數(shù)組類型【如:int[]、double[]等】注意:不支持:List[Integer]類型等List類型
2) String/CharSequence及其數(shù)組String[]雹锣、ArrayList[String]
3) Bundle 和 List<Bundle>
4) Serializable 注意:不支持List<Serializable>
5) Binder 和 List<Binder> 网沾,IBinder 和 List<IBinder>
6) Parcelable實現(xiàn)類重溫:Intent/Bundle傳遞支持的數(shù)據(jù)類型有:
* 基本數(shù)據(jù)類型和它的數(shù)組類型
* String/CharSequence和它的數(shù)組類型
* Serializable
* Parcelable
實現(xiàn)Parcelable接口
-
實現(xiàn)步驟
implements Parcelable
- 重寫
writeToParcel
方法,將你的對象序列化為一個Parcel對象蕊爵,即:將類的數(shù)據(jù)寫入外部提供的Parcel中辉哥,打包需要傳遞的數(shù)據(jù)到Parcel容器保存,以便從 Parcel容器獲取數(shù)據(jù)。 - 重寫
describeContents
方法醋旦,內(nèi)容接口描述恒水,默認返回0就可以。 - 實例化靜態(tài)內(nèi)部對象
CREATOR
實現(xiàn)接口Parcelable.Creator
-
沒有Parcelable成員的Parcelable接口實現(xiàn)示例:
/** * 測試:地址
-
Created by androidjp on 16-7-22.
*/
public class Address implements Parcelable{
///(可以)一般數(shù)據(jù)類型和String饲齐,如:String钉凌、int、Integer捂人、double御雕、Float等
public String country;
public String city;
public String street;
///(可以)Bindle類型【由于Bindle本身實現(xiàn)了Parcelable】
public Bundle bundle;
///(可以)Serializable類型
public Serializable serializable;
///(可以)Binder類型
public Binder binder;
public Integer i;
public int j;
public List<String> stringList;
public List<Bundle> bundleList;
// public List<Serializable> serializableList;
public ArrayList<IBinder> binderList;
// public List<Integer> integerList;
public int[] ints;public Address(String country, String city, String street) {
this.country = country;
this.city = city;
this.street = street;
}
//=========================================================
// 下面是Parcelable需要實現(xiàn)的方法
//=========================================================
protected Address(Parcel in) {
country = in.readString();
city = in.readString();
street = in.readString();
bundle = in.readBundle();
serializable = in.readSerializable();
binder = (Binder) in.readStrongBinder();
i = in.readInt();
j = in.readInt();
stringList = in.createStringArrayList();
bundleList = in.createTypedArrayList(Bundle.CREATOR);
binderList = in.createBinderArrayList();
ints = in.createIntArray();
}
/*- 讀取接口,目的是要從Parcel中構(gòu)造一個實現(xiàn)了Parcelable的類的實例處理滥搭。
- 因為實現(xiàn)類在這里還是不可知的酸纲,所以需要用到模板的方式,繼承類名通過模板參數(shù)傳入瑟匆。
- 為了能夠?qū)崿F(xiàn)模板參數(shù)的傳入闽坡,這里定義Creator嵌入接口,內(nèi)含兩個接口函數(shù)分別返回單個和多個繼承類實例。
*/
public static final Creator<Address> CREATOR = new Creator<Address>() {
@Override
public Address createFromParcel(Parcel in) {
return new Address(in);
}
@Override
public Address[] newArray(int size) {
return new Address[size];
}
};
/////內(nèi)容描述接口脓诡,基本不用管
@Override
public int describeContents() {
return 0;
}
//寫入接口函數(shù)无午,打包
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(country);
dest.writeString(city);
dest.writeString(street);
dest.writeBundle(bundle);
dest.writeSerializable(serializable);
dest.writeStrongBinder(binder);
dest.writeInt(i);dest.writeInt(j);
dest.writeStringList(stringList);
dest.writeTypedList(bundleList);
dest.writeBinderList(binderList);
dest.writeIntArray(ints);
}
}
* **加上Parcelable成員的Parcelable接口實現(xiàn)示例**:
/**
- 測試:學(xué)生
*/
public class Student implements Parcelable{
private int id;
private String name;
private Address home;////地址成員變量(已經(jīng)實現(xiàn)了Parcelable接口)
public Student(int id, String name, Address home) {
this.id = id;
this.name = name;
this.home = home;
}
//=========================================================
// 下面是Parcelable需要實現(xiàn)的方法
//=========================================================
protected Student(Parcel in) {
id = in.readInt();
name = in.readString();
home = in.readParcelable(Address.class.getClassLoader());
}
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 dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
dest.writeParcelable(home, flags);
}
}
## 擴展
---
1. 由于Parcelable對象不能向Serializable那樣將對象保存到文件中等持久化操作,那么祝谚,我的對象要怎么做宪迟?
答: `public class Student implements Parcelable,Serializable{……`,讓類同時實現(xiàn)兩個接口交惯,即可使他能夠序列化并存儲到文件中次泽。
2. 什么是Parcel?
答:簡單來說席爽,Parcel就是一個存放數(shù)據(jù)的容器意荤。Android中以Binder機制方式實現(xiàn)來IPC,就是使用了Parcel來進行Client和Server間的數(shù)據(jù)交互只锻,而且AIDL的數(shù)據(jù)也是通過Parcel來交互的玖像。同樣的,在Java中和C/C++中齐饮,都有Parcel的實現(xiàn)【Parcel在C/C++中捐寥,直接使用內(nèi)存來讀取數(shù)據(jù),所以此時Parcel它更加快速】
換句話理解Parcel:我們知道祖驱,類A和類B可能想要通信握恳,那么,要進行交流捺僻,A肯定不想把自己的實例(包括成員變量乡洼、方法等)整個復(fù)制到B那邊崇裁,并且,A和B在同一個線程束昵、甚至同個進程的不同線程都好說拔稳,如果是不同進程呢?那得怎么傳妻怎,通過網(wǎng)絡(luò)之類的咯壳炎?所以,就有了Parcel這個“打包”一說逼侦,A把A的一些信息進行說明匿辩,將這些說明打包(而不同打包自己的具體東西),然后把信息傳給B榛丢,B讀了之后铲球,根據(jù)A給的提示選擇,將選擇同樣用Parcel打包傳回給A晰赞,A收到就跑稼病,跑完數(shù)據(jù)后,返回結(jié)果又同樣Parcel裝著給到B掖鱼,整個通信過程類似這樣然走。