• android 进程间通信数据(二)------parcel的实现


    Serialize是java原生就自带的东西,我们可以看到android的源码

    所以看看android是如何实现parcel的,这对我们自己代码设计有什么启发。

    Parcel:

    在android中,parcel的源码如下:

    Frameworks/base/core/java/android/os/Parcel.java

        /**
         * Write an integer value into the parcel at the current dataPosition(),
         * growing dataCapacity() if needed.
         */
        public final void writeInt(int val) {
            nativeWriteInt(mNativePtr, val);
        }
    
        /**
         * Write a long integer value into the parcel at the current dataPosition(),
         * growing dataCapacity() if needed.
         */
        public final void writeLong(long val) {
            nativeWriteLong(mNativePtr, val);
        }

    常见方法:

           obtain()                     获得一个新的parcel ,相当于new一个对象
    
                dataSize()                   得到当前parcel对象的实际存储空间
    
                dataCapacity()               得到当前parcel对象的已分配的存储空间, >=dataSize()值  (以空间换时间)
    
                dataPostion()                获得当前parcel对象的偏移量(类似于文件流指针的偏移量)
    
                setDataPosition()            设置偏移量
    
                recyle()                     清空、回收parcel对象的内存
    
                writeInt(int)                写入一个整数
    
                writeFloat(float)            写入一个浮点数
    
                writeDouble(double)         写入一个双精度数
    
                writeString(string)          写入一个字符串
    
    
             当然,还有更多的writeXXX()方法,与之对应的就是readXXX(),具体方法请参阅SDK。
    
              其中几个值得注意的方法为:
    
                 writeException()           在Parcel队头写入一个异常
    
                 writeException()           Parcel队头写入“无异常“
    
                 readException()           在Parcel队头读取,若读取值为异常,则抛出该异常;否则,程序正常运行。

    我们来分析下:

    status_t Parcel::writeInt32(int32_t val)
    {
        return writeAligned(val);
    }
    template<class T>
    status_t Parcel::writeAligned(T val) {
        COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(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;
    }

    我们来分析writeAligned:

    首先是

    #define PAD_SIZE(s) (((s)+3)&~3)

     &~3:

    考虑16进制,~3 -> 0x11111100 在做&

    也就是说前面6位不变,最后2位为0.

    或者说,把最后2位变成0.也就是4的倍数。

    +3的目的是,把当前的值向上取最近的整除4的值,如果本身就是那就不变。

    所以就和宏的目的就是按4字节对齐!

    所以writeAligned是写入4字节对齐的内容。

    常见的是int32 和int64等。

    status_t Parcel::growData(size_t len)
    {
        size_t newSize = ((mDataSize+len)*3)/2;
        return (newSize <= mDataSize)
                ? (status_t) NO_MEMORY
                : continueWrite(newSize);
    }

    当内存不够的时候,会申请一块3/2块大小的内存,使得现在parcel可以使用。

    所以parcel本质的是最内存的操作,而且操作位memcpy等。

    查看continueWrite函数,由于很复杂,就不列出来了,

    看看关键的地方:

                size_t* objects =
                    (size_t*)realloc(mObjects, objectsSize*sizeof(size_t));

    扩大内存,啊哈。就是这个地方了。

    所以整个parcel的读写都在内存中操作的。

  • 相关阅读:
    第六届蓝桥杯JavaA组国(决)赛真题
    第六届蓝桥杯JavaA组国(决)赛真题
    第六届蓝桥杯JavaA组国(决)赛真题
    第六届蓝桥杯JavaA组国(决)赛真题
    C++ 实现 发送HTTP Get/Post请求 good
    Qt 窗口属性简介之Qt::WA_DeleteOnClose
    Qt 之 使用 https发送 HTTP请求(使用OPENSSL库)
    Delphi xe7 FireMonkey / Mobile (Android, iOS)生成 QR Code完整实例
    delphi android 录像(调用Java的功能)
    MVC 插件式开发
  • 原文地址:https://www.cnblogs.com/deman/p/4752222.html
Copyright © 2020-2023  润新知