分析Binder機制中的客戶端與服務器端進行實際操作ontransact()函數 :
[java]從中我們可以看到Parcel的重要性以及窺探它的使用情況,接下來,我主要分析它的存儲機制。
常用方法介紹:
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隊頭讀取,若讀取值為異常,則拋出該異常;否則,程序正常運行。
相信看了前面的值,對Parcel的使用該有了初步印象。那麼,Parcel的內部存儲機制是怎麼樣的?偏移量又是
什麼情況?讓我們回憶一下基本數據類型的取值范圍:
boolean 1bit 1字節
char 16bit 2字節
int 32bit 4字節
long 64bit 8字節
float 32bit 4字節
double 64bit 8字節
如果大家對C語言熟悉的話,C語言中結構體的內存對齊和Parcel采用的內存存放機制一樣,即讀取最小字節
為32bit,也即4個字節。高於4個字節的,以實際數據類型進行存放,但得為4byte的倍數。基本公式如下:
實際存放字節:
判別一: 32bit (<=32bit) 例如:boolean,char,int
判別二: 實際占用字節(>32bit) 例如:long,float,String,數組等
當我們使用readXXX()方法時,讀取方法也如上述:
實際讀取字節:
判別一: 32bit (<=32bit) 例如:boolean,char,int
判別二: 實際字節大小(>32bit) 例如:long,float,String,數值等
由上可以知道,當我們寫入/讀取一個數據時,偏移量至少為4byte(32bit),於是,偏移量的公式如下:
f(x)= 4x (x=0,1,…n)
事實上,我們可以顯示的通過setDataPostion(int postion) 來直接操作我們欲讀取數據時的偏移量。毫無疑問,
你可以設置任何偏移量,但所讀取的值是類型可能有誤。因此顯示設置偏移量讀取值的時候,需要小心。
另外一個注意點就是我們在writeXXX()和readXXX()時,導致的偏移量是共用的,例如,我們在writeInt(23)後,
此時的datapostion=4,如果我們想讀取5,簡單的通過readInt()是不行的,只能得到0。這時我們只能通過
setDataPosition(0)設置為起始偏移量,從起始位置讀取四個字節,即23。因此,在讀取某個值時,可能需要使用
setDataPostion(int postion)使偏移量裝換到我們的值處。
巧用setDataPosition()方法,當我們的parcel對象中只存在某一類型時,我們就可以通過這個方法來快速的讀取
所有值。具體方法如下:
[html]
由於可能存在讀取值的偏差,一個默認的取值規范為:
1、 讀取復雜對象時: 對象匹配時,返回當前偏移位置的該對象;
對象不匹配時,返回null對象 ;
2、 讀取簡單對象時: 對象匹配時,返回當前偏移位置的該對象 ;
對象不匹配時,返回0;