Parcel 是 Android 特有的数据序列化反序列化机制,不同于 Serializable,Parcel 主要用作进程间通信,是跨进程传输对象的工具。
Parcelable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 public interface Parcelable { public void writeToParcel (Parcel dest, @WriteFlags int flags) ; public interface Creator <T> { public T createFromParcel (Parcel source) ; public T[] newArray(int size); } }
Parcelable 是一个接口,实现该接口的类可以存储在 Parcel 对象中。
需要注意的是: 实现 writeToParcel() 和 createFromParcel() 时读写字段的顺序要保持一致,否则会出现 Parcel android.os.Parcel@60522f8: Unmarshalling unknown type code 3801137 at offset 244
错误。
Parcel Parcel(包裹) 主要用作进程间通信,而不是序列化
。效率高又节省内存。
Parcel 支持读写的常见数据类型整理如下:
Primitives 基本数据类型
Primitive Arrays 基本数据类型的数组
Parcelables 实现 Parcelable 接口的类
Bundles 一种 Key-Value 形式的数据包装类
Binder
FileDescriptor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 public final class Parcel { private long mNativePtr; private static final int POOL_SIZE = 6 ; private static final Parcel[] sOwnedPool = new Parcel [POOL_SIZE]; private static final Parcel[] sHolderPool = new Parcel [POOL_SIZE]; private static native int nativeDataSize (long nativePtr) ; public final static Parcelable.Creator<String> STRING_CREATOR = new Parcelable .Creator<String>() { public String createFromParcel (Parcel source) { return source.readString(); } public String[] newArray(int size) { return new String [size]; } }; public static Parcel obtain () { final Parcel[] pool = sOwnedPool; synchronized (pool) { Parcel p; for (int i=0 ; i<POOL_SIZE; i++) { p = pool[i]; if (p != null ) { pool[i] = null ; if (DEBUG_RECYCLE) { p.mStack = new RuntimeException (); } p.mReadWriteHelper = ReadWriteHelper.DEFAULT; return p; } } } return new Parcel (0 ); } public final void recycle () { if (DEBUG_RECYCLE) mStack = null ; freeBuffer(); final Parcel[] pool; if (mOwnsNativeParcelObject) { pool = sOwnedPool; } else { mNativePtr = 0 ; pool = sHolderPool; } synchronized (pool) { for (int i=0 ; i<POOL_SIZE; i++) { if (pool[i] == null ) { pool[i] = this ; return ; } } } } }
Parcel 创建过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private Parcel (long nativePtr) { init(nativePtr); } private void init (long nativePtr) { if (nativePtr != 0 ) { mNativePtr = nativePtr; mOwnsNativeParcelObject = false ; } else { mNativePtr = nativeCreate(); mOwnsNativeParcelObject = true ; } } private static native long nativeCreate () ;
进入 Native 层:
~\frameworks\base\core\jni\android_os_Parcel.cpp
1 2 3 4 5 static jlong android_os_Parcel_create (JNIEnv* env, jclass clazz) { Parcel* parcel = new Parcel (); return reinterpret_cast <jlong>(parcel); }
~\frameworks\native\libs\binder\Parcel.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Parcel::Parcel () { initState (); } void Parcel::initState () { mError = NO_ERROR; mData = 0 ; mDataSize = 0 ; mDataCapacity = 0 ; mDataPos = 0 ; mObjects = NULL ; mObjectsSize = 0 ; mObjectsCapacity = 0 ; mNextObjectHint = 0 ; mHasFds = false ; mFdsKnown = true ; mAllowFds = true ; mOwner = NULL ; mOpenAshmemSize = 0 ; if (gMaxFds == 0 ) { struct rlimit result; if (!getrlimit (RLIMIT_NOFILE, &result)) { gMaxFds = (size_t )result.rlim_cur; } else { ALOGW ("Unable to getrlimit: %s" , strerror (errno)); gMaxFds = 1024 ; } } }
参数
含义
mData
表示一块内存,用来存储 IPC 数据
mDataSize
mData 已存储的数据大小
mDataCapacity
mData 指示的内存大小
mDataPos
数据写入或读取的内存开始位置
mObjects
表示一块内存(该对象主要用作 Binder 记录相关对象的引用)
mObjectsSize
mObjects 已存储的数据大小
mObjectsCapacity
mObjects 指示的内存大小
参考 [1] Binder 基石-Parcel