參考資料:http://www.reibang.com/p/32a2ec8f35ae
https://www.cnblogs.com/tangZH/p/10998065.html
1.Parcelable的簡(jiǎn)單介紹
介紹Parcelable不得不先提一下Serializable接口,Serializable是Java為我們提供的一個(gè)標(biāo)準(zhǔn)化的序列化接口,那什么是序列化呢? ---- 簡(jiǎn)單來(lái)說(shuō)就是將對(duì)象轉(zhuǎn)換為可以傳輸?shù)亩M(jìn)制流(二進(jìn)制序列)的過(guò)程,這樣我們就可以通過(guò)序列化,轉(zhuǎn)化為可以在網(wǎng)絡(luò)傳輸或者保存到本地的流(序列),從而進(jìn)行傳輸數(shù)據(jù) ,那反序列化就是從二進(jìn)制流(序列)轉(zhuǎn)化為對(duì)象的過(guò)程.
那我們看一下Android源碼中的Parcelable
/**
* Interface for classes whose instances can be written to
* and restored from a {@link Parcel}. Classes implementing the Parcelable
* interface must also have a non-null static field called <code>CREATOR</code>
* of a type that implements the {@link Parcelable.Creator} interface.
*
* <p>A typical implementation of Parcelable is:</p>
*
* <pre>
* public class MyParcelable implements Parcelable {
* private int mData;
*
* public int describeContents() {
* return 0;
* }
*
* public void writeToParcel(Parcel out, int flags) {
* out.writeInt(mData);
* }
*
* public static final Parcelable.Creator<MyParcelable> CREATOR
* = new Parcelable.Creator<MyParcelable>() {
* public MyParcelable createFromParcel(Parcel in) {
* return new MyParcelable(in);
* }
*
* public MyParcelable[] newArray(int size) {
* return new MyParcelable[size];
* }
* };
*
* private MyParcelable(Parcel in) {
* mData = in.readInt();
* }
* }</pre>
*/
通過(guò)源碼中的介紹 可以知道,Parcelable接口的實(shí)現(xiàn)類是可以通過(guò)Parcel寫入和恢復(fù)數(shù)據(jù)的,并且必須要有一個(gè)非空的靜態(tài)變量 CREATOR, 而且還給了一個(gè)例子,這樣我們寫起來(lái)就比較簡(jiǎn)單了,但是簡(jiǎn)單的使用并不是我們的最終目的
通過(guò)查看Android源碼中Parcelable可以看出,Parcelable實(shí)現(xiàn)過(guò)程主要分為序列化,反序列化,描述三個(gè)過(guò)程,下面分別介紹下這三個(gè)過(guò)程
2 Parcel的簡(jiǎn)介
在介紹之前我們需要先了解Parcel是什么?Parcel翻譯過(guò)來(lái)是打包的意思,其實(shí)就是包裝了我們需要傳輸?shù)臄?shù)據(jù),然后在Binder中傳輸,也就是用于跨進(jìn)程傳輸數(shù)據(jù)
簡(jiǎn)單來(lái)說(shuō)器一,Parcel提供了一套機(jī)制很泊,可以將序列化之后的數(shù)據(jù)寫入到一個(gè)共享內(nèi)存中,其他進(jìn)程通過(guò)Parcel可以從這塊共享內(nèi)存中讀出字節(jié)流鹃愤,并反序列化成對(duì)象,下圖是這個(gè)過(guò)程的模型映挂。
Parcel可以包含原始數(shù)據(jù)類型(用各種對(duì)應(yīng)的方法寫入浮驳,比如writeInt(),writeFloat()等)物延,可以包含Parcelable對(duì)象,它還包含了一個(gè)活動(dòng)的IBinder對(duì)象的引用费尽,這個(gè)引用導(dǎo)致另一端接收到一個(gè)指向這個(gè)IBinder的代理IBinder赠群。
<meta charset="utf-8">
3 Parcelable中的三大過(guò)程介紹(序列化,反序列化,描述)
到這里,基本上關(guān)系都理清了,也明白簡(jiǎn)單的介紹和原理了,接下來(lái)在實(shí)現(xiàn)Parcelable之前,介紹下實(shí)現(xiàn)Parcelable的三大流程
首先寫一個(gè)類實(shí)現(xiàn)Parcelable接口,會(huì)讓我們實(shí)現(xiàn)兩個(gè)方法
1.3.1 描述
其中describeContents就是負(fù)責(zé)文件描述,首先看一下源碼的解讀
通過(guò)上面的描述可以看出,只針對(duì)一些特殊的需要描述信息的對(duì)象,需要返回1,其他情況返回0就可以
1.3.2 序列化
我們通過(guò)writeToParcel方法實(shí)現(xiàn)序列化,writeToParcel返回了Parcel,所以我們可以直接調(diào)用Parcel中的write方法,基本的write方法都有,對(duì)象和集合比較特殊下面單獨(dú)講,基本的數(shù)據(jù)類型除了boolean其他都有,Boolean可以使用int或byte存儲(chǔ)
舉個(gè)例子:我們將上面的User對(duì)象實(shí)現(xiàn)序列化,User對(duì)象包含三個(gè)字段 age,name,isMale
/**
* 該方法負(fù)責(zé)序列化
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
// boolean 可以使用int或byte方式進(jìn)行存儲(chǔ),怎么存就怎么取
dest.writeInt(isMale ? 1 : 0);
}
1.3.3 反序列化
反序列化需要定義一個(gè)CREATOR的變量,上面也說(shuō)了具體的做法,這里可以直接復(fù)制Android給的例子中的,也可以自己定義一個(gè)(名字千萬(wàn)不能改),通過(guò)匿名內(nèi)部類實(shí)現(xiàn)Parcelable中的Creator的接口
/**
* 負(fù)責(zé)反序列化
*/
public static final Creator<User> CREATOR = new Creator<User>() {
/**
* 從序列化后的對(duì)象中創(chuàng)建原始對(duì)象
*/
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
/**
* 創(chuàng)建指定長(zhǎng)度的原始對(duì)象數(shù)組
*/
@Override
public User[] newArray(int size) {
return new User[size];
}
};
public User(Parcel parcel) {
age = parcel.readInt();
name = parcel.readString();
isMale = parcel.readInt() == 1;
}
作者:MrQ_Android
鏈接:http://www.reibang.com/p/32a2ec8f35ae
來(lái)源:簡(jiǎn)書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)旱幼,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處查描。