1. 程式人生 > >淺析Android中Parcel類

淺析Android中Parcel類

淺析繫結遠端服務bindService基本原理與AIDL分析中,我們在使用服務呼叫遠端服務的函式時,到底可以傳遞哪些型別的引數類,在AIDL程序間傳遞複雜資料型別中,我們詳細解析了它可以傳遞的資料型別,那麼到底為什麼它只能傳遞這些資料型別。

其實我們在呼叫遠端服務的時候,會將引數進行統一的打包到Parcel中,然後在服務端會對Parcel進行統一的讀取,並且打包過程和讀取過程引數的順序要保持一致,為了保證包裹內參數順序,所以Android的SDK提供了aidl工具,它可以把一個aidl檔案轉化成一個java檔案,在java檔案中同時過載了transact和onTransact方法,進行統一存入包裹和讀取包裹引數,這樣設計者就可以把注意力放在伺服器程式碼本身上。

@Override 
public int add(int x, int y) throws android.os.RemoteException
{
    //得到傳遞的Parcle物件和返回的Parcel物件
    android.os.Parcel _data = android.os.Parcel.obtain();
    android.os.Parcel _reply = android.os.Parcel.obtain();
    int _result;
    try {
        //將引數一一的寫到Parcel中去
        _data.writeInterfaceToken
(DESCRIPTOR); _data.writeInt(x); _data.writeInt(y); mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; }
case
TRANSACTION_add: { //與客戶端的writeInterfaceToken對用,標識遠端服務的名稱 data.enforceInterface(DESCRIPTOR); //分別讀取了客戶端傳入的兩個引數 int _arg0; _arg0 = data.readInt(); int _arg1; _arg1 = data.readInt(); //這個地方會執行我們實現的add方法,就是MyService裡面實現的 int _result = this.add(_arg0, _arg1); //返回result由reply寫回 reply.writeNoException(); reply.writeInt(_result); return true; }

上面程式碼就充分的證明了我們上面所說的,也可以清晰的看到整個打包過程和解包過程。

下面我們需要做的就是看看Parcel這個類,從這個類我們就可以知道service到底可以傳遞哪些型別的引數,因為我們只需要知道哪些型別的引數可以被打包就說明哪些型別的引數可以被傳遞。

這個類就相當於一個包裹,把我們要傳遞的引數放進去。下面我們就整理整理它可以存放哪些資料。

//byte[]陣列型別
public final void writeByteArray(byte[] b)

public final void writeByteArray(byte[] b, int offset, int len)
//int型別
public final void writeInt(int val)
//long型別
public final void writeLong(long val)
//float型別
public final void writeFloat(float val)
//double型別
public final void writeDouble(double val)
//String型別
public final void writeString(String val)
//IBinder型別
public final void writeStrongBinder(IBinder val)
//IInterface型別
public final void writeStrongInterface(IInterface val)
//FileDescriptor型別
public final void writeFileDescriptor(FileDescriptor val)
//byte型別
public final void writeByte(byte val) 
//Map型別,注意因為這個函式的本質也是對Map中的資料依次寫入
//所以Map中的資料型別也要滿足這裡所列舉的型別
public final void writeMap(Map val)
//Bundle型別
public final void writeBundle(Bundle val)
//List型別,注意跟writeMap一樣
public final void writeList(List val)
//Object[]陣列型別,注意跟writeMap一樣
public final void writeArray(Object[] val)
//SparseArray<Object>型別,注意跟writeMap一樣
public final void writeSparseArray(SparseArray<Object> val) 
//SparseBooleanArray型別
public final void writeSparseBooleanArray(SparseBooleanArray val)
//boolean[]型別
public final void writeBooleanArray(boolean[] val) 
//char[]型別
public final void writeCharArray(char[] val)
//int[]型別
public final void writeIntArray(int[] val)
//long[]型別
public final void writeLongArray(long[] val)
//float[]型別
public final void writeFloatArray(float[] val)
//double[]型別
public final void writeDoubleArray(double[] val)
//String[]型別
public final void writeStringArray(String[] val)
//IBinder[]型別
public final void writeBinderArray(IBinder[] val) 
//List<T>型別<T extends Parcelable>
public final <T extends Parcelable> void writeTypedList(List<T> val)
//List<String>型別
public final void writeStringList(List<String> val)
//List<IBinder>型別
public final void writeBinderList(List<IBinder> val)
//T[]型別<T extends Parcelable>
public final <T extends Parcelable> void writeTypedArray(T[] val,
            int parcelableFlags)

//Parcelable型別
public final void writeParcelable(Parcelable p, int parcelableFlags)
//Serializable型別
public final void writeSerializable(Serializable s)
//Exception型別
public final void writeException(Exception e)

上面列舉了它可以打包的所有資料型別,也就算AIDL可以傳遞的所有資料型別。具體實現可以自行看原始碼。

=================================================
關於Parcelable的自動生成開源專案: