Android源码之Parcel.docx
《Android源码之Parcel.docx》由会员分享,可在线阅读,更多相关《Android源码之Parcel.docx(4页珍藏版)》请在冰豆网上搜索。
![Android源码之Parcel.docx](https://file1.bdocx.com/fileroot1/2022-11/16/2b375467-c063-4854-846a-36dfc2680fd6/2b375467-c063-4854-846a-36dfc2680fd61.gif)
Android源码之Parcel
Android源码之Parcel
Parcel的意思是“打包”。
在Android中,Parcel的作用类似于Java中的serialize,即对象的序列化。
Android系统定位为内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC机制,必然要求使用性能更出色的对象传输方式。
在这样的环境下,Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。
Parcel的最主要作用是在各个activity之间传递数据。
Android开发中,很经常在各activity之间传递数据,而跟据Android的设计架构,即使同一个程序中的Activity都不一定运行在同一个进程中,所以处理数据传递时你不能老假设两个activity都运行于同一进程,那么只能按进程间传递数据来处理,使之具有最广泛的适应性。
Parcel的接口主要有以下几类:
一、Parcel的获取与释放
[java]viewplaincopypublicstaticParcelobtain(){finalParcel[]pool=sOwnedPool;synchronized(pool){Parcelp;for(inti=0;i<POOL_SIZE;i++){p=pool[i];if(p!
=null){pool[i]=null;if(DEBUG_RECYCLE){p.mStack=newRuntimeException();}returnp;}}}returnnewParcel(0);}publicfinalvoidrecycle(){if(DEBUG_RECYCLE)mStack=null;freeBuffer();finalParcel[]pool=mOwnObject!
=0?
sOwnedPool:
sHolderPool;synchronized(pool){for(inti=0;i<POOL_SIZE;i++){if(pool[i]==null){pool[i]=this;return;}}}}
获取接口obtain是从一个已分配的Parcel池中取得一个Parcel,即sOwnedPool,其定义如下:
[java]viewplaincopyprivatestaticfinalintPOOL_SIZE=6;privatestaticfinalParcel[]sOwnedPool=newParcel[POOL_SIZE];privatestaticfinalParcel[]sHolderPool=newParcel[POOL_SIZE];
当使用完获得的Parcel后,最好使用recycle将其释放回池,以便下次使用,否则导致Parcel池无可分配资源而new新对象。
幸运的是,eclipse会给出此类的警告提示。
二、Parcel内部指针的移动
[java]viewplaincopypublicfinalnativeintdataSize();publicfinalnativeintdataAvail();publicfinalnativeintdataPosition();publicfinalnativeintdataCapacity();publicfinalnativevoidsetDataSize(intsize);publicfinalnativevoidsetDataPosition(intpos);publicfinalnativevoidsetDataCapacity(intsize);
由于Parcel的读写是直接在内存中的,所以这几个接口就是指示当前的读写指针,类似于Linux下的文件读写操作:
dataSize:
返回当前内存块中总共的数据
dataPosition:
返回当前读操作指针
dataAvail:
返回当前可读的数据,即dataSize-dataPosition
dataCapacity:
返回当前内存块的容量(在不重新分配内存的前提下),dataCapacity-dataSize即为可写入的数据量三、数据读写类
1、序列化与反序列化
publicfinalnativebyte[]marshall();
publicfinalnativevoidunmarshall(byte[]data,intoffest,intlength);
作用类似于序列化和反序列化。
即将当前Parcel的数据序列化为byte数组,或者将byte数组反序列化到当前Parcel中。
注:
unmarshall后,如果要读取数据,首先需要将文件指针移动到初始化位置,即setDataPosition(0)。
2、基本数据类型的读写
privatenativevoidwriteNative(byte[]
b,intoffset,intlen);
publicfinalnativevoidwriteInt(intval);
publicfinalnativevoidwriteLong(longval);
publicfinalnativevoidwriteFloat(floatval);
publicfinalnativevoidwriteDouble(doubleval);
publicfinalnativevoidwriteString(Stringval);
publicfinalnativevoidwriteStrongBinder(IBinderval);
publicfinalnativevoidwriteFileDescriptor(FileDescriptorval);publicfinalnativeintreadInt();
publicfinalnativelongreadLong();
publicfinalnativefloatreadFloat();
publicfinalnativedoublereadDouble();
publicfinalnativeStringreadString();
publicfinalnativeIBinderreadStrongBinder();全部都是native方法,通过JNI来调用底层实现。
其余类型的读写都是在基本数据类型的基础上得来的。
如:
[java]viewplaincopypublicfinalvoidwriteByte(byteval){writeInt(val);}publicfinalbytereadByte(){return(byte)(readInt()&0xff);}
可见,byte在Parcel中也占用四个字节。
3、Array类型的读写
Array类型的接口按类型来分,如boolean[]/char[]/int[]/float[]/double[]/String[],而每一种类型都包含三个接口:
publicfinalvoidwriteXXXArray(boolean[]val);publicfinalboolean[]createXXXArray();publicfinalvoidreadXXXArray(boolean[]val);以boolean类型为例:
其源码如下:
[java]viewplaincopypublicfinalvoidwriteBooleanArray(boolean[]val){if(val!
=null){intN=val.length;writeInt(N);for(inti=0;i<N;i++){writeInt(val[i]?
1:
0);}}else{writeInt(-1);}}publicfinalboolean[]createBooleanArray(){intN=readInt();//>>2asafastdivide-by-4worksinthecreate*Array()functions//becausedataAvail()willneverreturnanegativenumber.4is//thesizeofastoredbooleaninthestream.if(N>=0&&N<=(dataAvail()>>2)){boolean[]val=newboolean[N];for(inti=0;i<N;i++){val[i]=readInt()!
=0;}returnval;}else{returnnull;}}publicfinalvoidreadBooleanArray(boolean[]val){intN=readInt();if(N==val.length){for(inti=0;i<N;i++){val[i]=readInt()!
=0;}}else{thrownewRuntimeException("badarraylengths");}}
可见,其write操作的过程是先以整形的方式写入Array的长度,然后依次写入Array的每一个元素。
而读操作的过程则正好相反。
注:
从以上示例看出,boolean类型在Parcel中也占据四个字节。
4、通用接口
[java]viewplaincopypublicfinalvoidwriteValue(Objectv){if(v==null){writeInt(VAL_NULL);}elseif(vinstanceofString){writeInt(VAL_STRING);writeString((String)v);}elseif(vinstanceofInteger){writeInt(VAL_INTEGER);writeInt((Integer)v);}elseif(vinstanceofMap){writeInt(VAL_MAP);writeMap((Map)v);}elseif(vinstanceofBundle){//MustbebeforeParcelablewriteInt(VAL_BUNDLE);writeBundle((Bundle)v);}elseif(vinstanceofParcelable){writeInt(VAL_PARCELABLE);writeParcelable((Parcelable)v,0);}elseif(vinstanceofShort){writeInt(VAL_SHORT);writeInt(((Short)v).intValue());}elseif(vinstanceofLong){writeInt(VAL_LONG);writeLong((Long)v);}elseif(vinst