android 處理序間通訊資料(二)------parcel的實現,androidparcel
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的讀寫都在記憶體中操作的。