分享

Android源码之Parcel

 android之情殇 2014-02-27

Parcel的意思是“打包”。在Android中,Parcel的作用类似于Java中的serialize,即对象的序列化。Android系统定位为内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC机制,必然要求使用性能更出色的对象传输方式。在这样的环境下,Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。

Parcel的最主要作用是在各个activity之间传递数据。Android开发中,很经常在各activity之间传递数据,而跟据Android的设计架构,即使同一个程序中的Activity都不一定运行在同一个进程中,所以处理数据传递时你不能老假设两个activity都运行于同一进程,那么只能按进程间传递数据来处理,使之具有最广泛的适应性。

Parcel的接口主要有以下几类:

一、Parcel的获取与释放

  1. public static Parcel obtain() {  
  2.     final Parcel[] pool = sOwnedPool;  
  3.     synchronized (pool) {  
  4.         Parcel p;  
  5.         for (int i=0; i<POOL_SIZE; i++) {  
  6.             p = pool[i];  
  7.             if (p != null) {  
  8.                 pool[i] = null;  
  9.                 if (DEBUG_RECYCLE) {  
  10.                     p.mStack = new RuntimeException();  
  11.                 }  
  12.                 return p;  
  13.             }  
  14.         }  
  15.     }  
  16.     return new Parcel(0);  
  17. }  
  18.   
  19. public final void recycle() {  
  20.     if (DEBUG_RECYCLE) mStack = null;  
  21.     freeBuffer();  
  22.     final Parcel[] pool = mOwnObject != 0 ? sOwnedPool : sHolderPool;  
  23.     synchronized (pool) {  
  24.         for (int i=0; i<POOL_SIZE; i++) {  
  25.             if (pool[i] == null) {  
  26.                 pool[i] = this;  
  27.                 return;  
  28.             }  
  29.         }  
  30.     }  
  31. }  

获取接口obtain是从一个已分配的Parcel池中取得一个Parcel,即sOwnedPool,其定义如下:

  1. private static final int POOL_SIZE = 6;  
  2. private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE];  
  3. private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE];  

当使用完获得的Parcel后,最好使用recycle将其释放回池,以便下次使用,否则导致Parcel池无可分配资源而new新对象。幸运的是,eclipse会给出此类的警告提示。


二、Parcel内部指针的移动

  1. public final native int dataSize();  
  2. public final native int dataAvail();  
  3. public final native int dataPosition();  
  4. public final native int dataCapacity();  
  5. public final native void setDataSize(int size);  
  6. public final native void setDataPosition(int pos);  
  7. public final native void setDataCapacity(int size);  

由于Parcel的读写是直接在内存中的,所以这几个接口就是指示当前的读写指针,类似于Linux下的文件读写操作:

dataSize:返回当前内存块中总共的数据

dataPosition:返回当前读操作指针

dataAvail:返回当前可读的数据,即dataSize - dataPosition

dataCapacity:返回当前内存块的容量(在不重新分配内存的前提下),dataCapacity - dataSize即为可写入的数据量


三、数据读写类

1、序列化与反序列化

public final native byte[] marshall();
public final native void unmarshall(byte[] data, int offest, int length);

作用类似于序列化和反序列化。即将当前Parcel的数据序列化为byte数组,或者将byte数组反序列化到当前Parcel中。

注:unmarshall后,如果要读取数据,首先需要将文件指针移动到初始化位置,即setDataPosition(0)。


2、基本数据类型的读写

private native void writeNative(byte[] b, int offset, int len);
public final native void writeInt(int val);
public final native void writeLong(long val);
public final native void writeFloat(float val);
public final native void writeDouble(double val);
public final native void writeString(String val);
public final native void writeStrongBinder(IBinder val);
public final native void writeFileDescriptor(FileDescriptor val);

public final native int readInt();
public final native long readLong();
public final native float readFloat();
public final native double readDouble();
public final native String readString();
public final native IBinder readStrongBinder();

全部都是native方法,通过JNI来调用底层实现。其余类型的读写都是在基本数据类型的基础上得来的。如:

  1. public final void writeByte(byte val) {  
  2.     writeInt(val);  
  3. }  
  4. public final byte readByte() {  
  5.     return (byte)(readInt() & 0xff);  
  6. }  

可见,byte在Parcel中也占用四个字节。


3、Array类型的读写

Array类型的接口按类型来分,如boolean[]/char[]/int[]/float[]/double[]/String[],而每一种类型都包含三个接口:

public final void writeXXXArray(boolean[] val);

public final boolean[] createXXXArray();

public final void readXXXArray(boolean[] val);

以boolean类型为例:其源码如下:

  1. public final void writeBooleanArray(boolean[] val) {  
  2.     if (val != null) {  
  3.         int N = val.length;  
  4.         writeInt(N);  
  5.         for (int i=0; i<N; i++) {  
  6.             writeInt(val[i] ? 1 : 0);  
  7.         }  
  8.     } else {  
  9.         writeInt(-1);  
  10.     }  
  11. }  
  12.   
  13. public final boolean[] createBooleanArray() {  
  14.     int N = readInt();  
  15.     // >>2 as a fast divide-by-4 works in the create*Array() functions  
  16.     // because dataAvail() will never return a negative number.  4 is  
  17.     // the size of a stored boolean in the stream.  
  18.     if (N >= 0 && N <= (dataAvail() >> 2)) {  
  19.         boolean[] val = new boolean[N];  
  20.         for (int i=0; i<N; i++) {  
  21.             val[i] = readInt() != 0;  
  22.         }  
  23.         return val;  
  24.     } else {  
  25.         return null;  
  26.     }  
  27. }  
  28.   
  29. public final void readBooleanArray(boolean[] val) {  
  30.     int N = readInt();  
  31.     if (N == val.length) {  
  32.         for (int i=0; i<N; i++) {  
  33.             val[i] = readInt() != 0;  
  34.         }  
  35.     } else {  
  36.         throw new RuntimeException("bad array lengths");  
  37.     }  
  38. }  

可见,其write操作的过程是先以整形的方式写入Array的长度,然后依次写入Array的每一个元素。而读操作的过程则正好相反。

注:从以上示例看出,boolean类型在Parcel中也占据四个字节。


4、通用接口

  1. public final void writeValue(Object v) {  
  2.     if (v == null) {  
  3.         writeInt(VAL_NULL);  
  4.     } else if (v instanceof String) {  
  5.         writeInt(VAL_STRING);  
  6.         writeString((String) v);  
  7.     } else if (v instanceof Integer) {  
  8.         writeInt(VAL_INTEGER);  
  9.         writeInt((Integer) v);  
  10.     } else if (v instanceof Map) {  
  11.         writeInt(VAL_MAP);  
  12.         writeMap((Map) v);  
  13.     } else if (v instanceof Bundle) {  
  14.         // Must be before Parcelable  
  15.         writeInt(VAL_BUNDLE);  
  16.         writeBundle((Bundle) v);  
  17.     } else if (v instanceof Parcelable) {  
  18.         writeInt(VAL_PARCELABLE);  
  19.         writeParcelable((Parcelable) v, 0);  
  20.     } else if (v instanceof Short) {  
  21.         writeInt(VAL_SHORT);  
  22.         writeInt(((Short) v).intValue());  
  23.     } else if (v instanceof Long) {  
  24.         writeInt(VAL_LONG);  
  25.         writeLong((Long) v);  
  26.     } else if (v instanceof Float) {  
  27.         writeInt(VAL_FLOAT);  
  28.         writeFloat((Float) v);  
  29.     } else if (v instanceof Double) {  
  30.         writeInt(VAL_DOUBLE);  
  31.         writeDouble((Double) v);  
  32.     } else if (v instanceof Boolean) {  
  33.         writeInt(VAL_BOOLEAN);  
  34.         writeInt((Boolean) v ? 1 : 0);  
  35.     } else if (v instanceof CharSequence) {  
  36.         // Must be after String  
  37.         writeInt(VAL_CHARSEQUENCE);  
  38.         writeCharSequence((CharSequence) v);  
  39.     } else if (v instanceof List) {  
  40.         writeInt(VAL_LIST);  
  41.         writeList((List) v);  
  42.     } else if (v instanceof SparseArray) {  
  43.         writeInt(VAL_SPARSEARRAY);  
  44.         writeSparseArray((SparseArray) v);  
  45.     } else if (v instanceof boolean[]) {  
  46.         writeInt(VAL_BOOLEANARRAY);  
  47.         writeBooleanArray((boolean[]) v);  
  48.     } else if (v instanceof byte[]) {  
  49.         writeInt(VAL_BYTEARRAY);  
  50.         writeByteArray((byte[]) v);  
  51.     } else if (v instanceof String[]) {  
  52.         writeInt(VAL_STRINGARRAY);  
  53.         writeStringArray((String[]) v);  
  54.     } else if (v instanceof CharSequence[]) {  
  55.         // Must be after String[] and before Object[]  
  56.         writeInt(VAL_CHARSEQUENCEARRAY);  
  57.         writeCharSequenceArray((CharSequence[]) v);  
  58.     } else if (v instanceof IBinder) {  
  59.         writeInt(VAL_IBINDER);  
  60.         writeStrongBinder((IBinder) v);  
  61.     } else if (v instanceof Parcelable[]) {  
  62.         writeInt(VAL_PARCELABLEARRAY);  
  63.         writeParcelableArray((Parcelable[]) v, 0);  
  64.     } else if (v instanceof Object[]) {  
  65.         writeInt(VAL_OBJECTARRAY);  
  66.         writeArray((Object[]) v);  
  67.     } else if (v instanceof int[]) {  
  68.         writeInt(VAL_INTARRAY);  
  69.         writeIntArray((int[]) v);  
  70.     } else if (v instanceof long[]) {  
  71.         writeInt(VAL_LONGARRAY);  
  72.         writeLongArray((long[]) v);  
  73.     } else if (v instanceof Byte) {  
  74.         writeInt(VAL_BYTE);  
  75.         writeInt((Byte) v);  
  76.     } else if (v instanceof Serializable) {  
  77.         // Must be last  
  78.         writeInt(VAL_SERIALIZABLE);  
  79.         writeSerializable((Serializable) v);  
  80.     } else {  
  81.         throw new RuntimeException("Parcel: unable to marshal value " + v);  
  82.     }  
  83. }  
  84.   
  85. public final Object readValue(ClassLoader loader) {  
  86.     int type = readInt();  
  87.   
  88.     switch (type) {  
  89.     case VAL_NULL:  
  90.         return null;  
  91.     case VAL_STRING:  
  92.         return readString();  
  93.     case VAL_INTEGER:  
  94.         return readInt();  
  95.     case VAL_MAP:  
  96.         return readHashMap(loader);  
  97.     case VAL_PARCELABLE:  
  98.         return readParcelable(loader);  
  99.     case VAL_SHORT:  
  100.         return (short) readInt();  
  101.     case VAL_LONG:  
  102.         return readLong();  
  103.     case VAL_FLOAT:  
  104.         return readFloat();  
  105.     case VAL_DOUBLE:  
  106.         return readDouble();  
  107.     case VAL_BOOLEAN:  
  108.         return readInt() == 1;  
  109.     case VAL_CHARSEQUENCE:  
  110.         return readCharSequence();  
  111.     case VAL_LIST:  
  112.         return readArrayList(loader);  
  113.     case VAL_BOOLEANARRAY:  
  114.         return createBooleanArray();          
  115.     case VAL_BYTEARRAY:  
  116.         return createByteArray();  
  117.     case VAL_STRINGARRAY:  
  118.         return readStringArray();  
  119.     case VAL_CHARSEQUENCEARRAY:  
  120.         return readCharSequenceArray();  
  121.     case VAL_IBINDER:  
  122.         return readStrongBinder();  
  123.     case VAL_OBJECTARRAY:  
  124.         return readArray(loader);  
  125.     case VAL_INTARRAY:  
  126.         return createIntArray();  
  127.     case VAL_LONGARRAY:  
  128.         return createLongArray();  
  129.     case VAL_BYTE:  
  130.         return readByte();  
  131.     case VAL_SERIALIZABLE:  
  132.         return readSerializable();  
  133.     case VAL_PARCELABLEARRAY:  
  134.         return readParcelableArray(loader);  
  135.     case VAL_SPARSEARRAY:  
  136.         return readSparseArray(loader);  
  137.     case VAL_SPARSEBOOLEANARRAY:  
  138.         return readSparseBooleanArray();  
  139.     case VAL_BUNDLE:  
  140.         return readBundle(loader); // loading will be deferred  
  141.     default:  
  142.         int off = dataPosition() - 4;  
  143.         throw new RuntimeException(  
  144.             "Parcel " + this + ": Unmarshalling unknown type code " + type + " at offset " + off);  
  145.     }  
  146. }  

这两个接口依赖于前面基本类型的接口,内部通过instanceof关键字类判断数据类型。各个类型常量定义如下:

  1. private static final int VAL_NULL = -1;  
  2. private static final int VAL_STRING = 0;  
  3. private static final int VAL_INTEGER = 1;  
  4. private static final int VAL_MAP = 2;  
  5. private static final int VAL_BUNDLE = 3;  
  6. private static final int VAL_PARCELABLE = 4;  
  7. private static final int VAL_SHORT = 5;  
  8. private static final int VAL_LONG = 6;  
  9. private static final int VAL_FLOAT = 7;  
  10. private static final int VAL_DOUBLE = 8;  
  11. private static final int VAL_BOOLEAN = 9;  
  12. private static final int VAL_CHARSEQUENCE = 10;  
  13. private static final int VAL_LIST  = 11;  
  14. private static final int VAL_SPARSEARRAY = 12;  
  15. private static final int VAL_BYTEARRAY = 13;  
  16. private static final int VAL_STRINGARRAY = 14;  
  17. private static final int VAL_IBINDER = 15;  
  18. private static final int VAL_PARCELABLEARRAY = 16;  
  19. private static final int VAL_OBJECTARRAY = 17;  
  20. private static final int VAL_INTARRAY = 18;  
  21. private static final int VAL_LONGARRAY = 19;  
  22. private static final int VAL_BYTE = 20;  
  23. private static final int VAL_SERIALIZABLE = 21;  
  24. private static final int VAL_SPARSEBOOLEANARRAY = 22;  
  25. private static final int VAL_BOOLEANARRAY = 23;  
  26. private static final int VAL_CHARSEQUENCEARRAY = 24;  




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多