一.先從Serialize說起

我們都知道JAVA中的Serialize機制,譯成序列化、序列化……,其作用是能將資料物件存入位元組流當中,在需要時重新生成物件。主要應用是利用外部儲存裝置儲存物件狀態,以及通過網路傳輸物件等。

二.Android中的新的序列化機制

Android系統中,定位為針對記憶體受限的裝置,因此對效能要求更高,另外系統中採用了新的IPC(程序間通訊)機制,必然要求使用效能更出色的物件傳輸方式。在這樣的環境下,Parcel被設計出來,其定位就是輕量級的高效的物件序列化和反序列化機制。

三.Parcel類的背後

Framework中有parcel類,原始碼路徑是:

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

典型的原始碼片斷如下:

  

從中我們看到,從這個源程式檔案中我們看不到真正的功能是如何實現的,必須透過JNI往下走了。於是,Frameworks/base/core/jni/android_util_Binder.cpp中找到了線索

 

從這裡我們可以得到的資訊是函式的實現依賴於Parcel指標,因此還需要找到Parcel的類定義,注意,這裡的類已經是用C++語言實現的了。

找到Frameworks/base/include/binder/parcel.hFrameworks/base/libs/binder/parcel.cpp。終於找到了最終的實現程式碼了。

有興趣的朋友可以自己讀一下,不難理解,這裡把基本的思路總結一下:

1.整個讀寫全是在記憶體中進行,主要是通過malloc()realloc()memcpy()等記憶體操作進行,所以效率比JAVA序列化中使用外部儲存器會高很多;

2.讀寫時是4位元組對齊的,可以看到#define PAD_SIZE(s) (((s)+3)&~3)這句巨集定義就是在做這件事情;

3.如果預分配的空間不夠時newSize = ((mDataSize+len)*3)/2;會一次多分配50%

4.對於普通資料,使用的是mData記憶體地址,對於IBinder型別的資料以及FileDescriptor使用的是mObjects記憶體地址。後者是通過flatten_binder()unflatten_binder()實現的,目的是反序列化時讀出的物件就是原物件而不用重新new一個新物件。

好了,這就是Parcel背後的動作,全是在一塊記憶體裡進行讀寫操作,就不囉嗦了,把parcel的程式碼貼在這供沒有原始碼的朋友參考吧。接下來我會用一個小DEMO演示一下Parcel類在應用程式中的使用,詳見《探索Android中的Parcel機制(下)》。

 

本文的原始碼使用的是Android 2.1版本。