在浅析绑定远程服务bindService基本原理与AIDL分析中,我们在使用服务调用远程服务的函数时,到底可以传递哪些类型的参数类,在AIDL进程间传递复杂数据类型中,我们详细解析了它可以传递的数据类型,那么到底为什么它只能传递这些数据类型。
其实我们在调用远程服务的时候,会将参数进行统一的打包到Parcel中,然后在服务端会对Parcel进行统一的读取,并且打包过程和读取过程参数的顺序要保持一致,为了保证包裹内参数顺序,所以Android的SDK提供了aidl工具,它可以把一个aidl文件转化成一个java文件,在java文件中同时重载了transact和onTransact方法,进行统一存入包裹和读取包裹参数,这样设计者就可以把注意力放在服务器代码本身上。
下面我们摘取浅析绑定远程服务bindService基本原理与AIDL分析中的代码如下:
@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的自动生成开源项目: