Parcel


Parcel创建

构造方法私有
静态方法Parcel#obtain和Parcel#obtain(long obj)创建。

public static Parcel obtain() {
    final Parcel[] pool = sOwnedPool;
    synchronized (pool) {
        Parcel p;
        for (int i=0; i

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(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(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(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

从0遍历每个数组元素,如果为空,则将数组该项设置调用者Parcel。
若是自己创建的底层,则freeBuffer释放。
JNI#nativeFreeBuffer方法

static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jlong nativePtr)
{
    Parcel* parcel = reinterpret_cast(nativePtr);
    if (parcel != NULL) {
        parcel->freeData();
    }
}

native层Parcel对象freeData方法。


任重而道远

你可能感兴趣的:(Parcel)