Parcel创建
构造方法私有。
静态方法Parcel#obtain和Parcel#obtain(long obj)创建。
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();
}
return p;
}
}
}
return new Parcel(0);
}
sOwnedPool内部Parcel池,数组,可存储POOL_SIZE个Parcel,POOL_SIZE是6,从0开始遍历,找到数组中不空的位置,返回Parcel,置空该位置。
数组池中全空,新建Parcel对象返回。参数是0。
sOwnedPool池中存储的都是自己创建(nativeCreate)native层Parcel的Parcel,sHolderPool池存储的是传入native层指针的Parcel。
Parcel构造方法触发Parcel#init初始化。
private void init(long nativePtr) {
if (nativePtr != 0) {
mNativePtr = nativePtr;
mOwnsNativeParcelObject = false;
} else {
mNativePtr = nativeCreate();
mOwnsNativeParcelObject = true;
}
}
若nativePtr是0,JNI#nativeCreate创建native层Parcel对象,返回mNativePtr指针。若nativePtr非0,将其他Java层Parcel存储的native层指针赋值mNativePtr。
JNI#android_os_Parcel_create方法
static jlong android_os_Parcel_create(JNIEnv* env, jclass clazz)
{
Parcel* parcel = new Parcel();
return reinterpret_cast<jlong>(parcel);
}
创建native层Parcel对象。
因此,Java层Parcel对象引用native层Parcel的指针。
Parcel#writeInt分析
Parcel#writeInt方法
public final void writeInt(int val) {
nativeWriteInt(mNativePtr, val);
}
触发JNI#nativeWriteInt方法。
static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jlong nativePtr, jint val) {
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
signalExceptionForError(env, clazz, err);
}
}
}
native层Parcel对象,writeInt32会调用writeAligned方法。
status_t Parcel::writeAligned(T val) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
*reinterpret_cast<T*>(mData+mDataPos) = val;
return finishWrite(sizeof(val));
}
status_t err = growData(sizeof(val));
if (err == NO_ERROR) goto restart_write;
return err;
}
mData代表写入的初始地址值,字节类型指针。mDataPos为当前指向的地址值偏移量。val计算出占用几个字节。当mDataPos偏移量加上val字节数不大于mDataCapacity容量时,mDataPos偏移再加上mData,为放置val的地址,通过*取指向的内容,设置为val,最后finishWrite更新mDataPos自增val的字节大小。
若大于mDataCapacity,则growData扩容后restart_write重新设置。
综上,Parcel写入的数据存储在native内存空间。
回收Parcel
Parcel#recycle()
public final void recycle() {
freeBuffer();
final Parcel[] pool;
if (mOwnsNativeParcelObject) {//构造方法自己创建的底层,mNativePtr值不变。
pool = sOwnedPool;//存入sOwnedPool数组池
} else {
mNativePtr = 0;//本来就是传入的底层指针,设为0。
pool = sHolderPool;
}
synchronized (pool) {
for (int i=0; i<POOL_SIZE; i++) {
if (pool[i] == null) {
pool[i] = this;
return;
}
}
}
}
从0遍历每个数组元素,如果为空,则将数组该项设置调用者Parcel。
若是自己创建的底层,则freeBuffer释放。
JNI#nativeFreeBuffer方法
static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
{
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
parcel->freeData();
}
}
native层Parcel对象freeData方法。
任重而道远