Binder机制,从Java到C (4. Parcel)

2014-11-24 03:31:52 · 作者: · 浏览: 0
1. 远程调用的数据传输
在远程的函 中,必然会需要传递一些数据,那这些数据是怎么传输的呢?
在IPC中,Proxy端的作用就是将一些参数打包,然后发送出去,下面是在Proxy端经常会遇见的调用远程方法的代码。
可以看到,发送和接收的数据都是通过Parcel 打包的。
复制代码
1 class ActivityManagerProxy implements IActivityManager
2 {
3 public int startActivity(IApplicationThread caller, Intent intent,
4 String resolvedType, IBinder resultTo, String resultWho, int requestCode,
5 int startFlags, String profileFile,
6 ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
7 Parcel data = Parcel.obtain();
8 Parcel reply = Parcel.obtain();
9 data.writeInterfaceToken(IActivityManager.descriptor);
10 data.writeStrongBinder(caller != null caller.asBinder() : null);
11 intent.writeToParcel(data, 0);
12 data.writeString(resolvedType);
13 data.writeStrongBinder(resultTo);
14 data.writeString(resultWho);
15 ...
16 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
17 reply.readException();
18 int result = reply.readInt();
19 ...
20 return result;
21 }
22 }
复制代码
一些基本类型,比如String,int可以直接写进Parcel中,那么对于一些比较复杂的数据类型,比如一些自己定义的对象,要怎么写进Parcel里呢?
我 通过一个类new一个对象 ,这个object的有效范围只是在一个进程里。如果通过IPC机制直接传递一个object是不现实的。因为 Java环境里的对象是通过引用 访问的,一个object对其他object,会是通过一个类似指针的引用 访问的,会涉及到类似地址的访问。
所以在传递复杂对象 ,必须把object拆解成中间形式,然後在IPC里传输这种中间格式。
那怎么把一个object拆解成中间形式呢?
--> 就需要Parcelable接口了
2.Parcelable
当需要在进程间传输一个object ,这个object必 实现Parcelable接口的属性或方法。
例如:
在单进程中,有这样一个类:
复制代码
1 class TaskInfo {
2 public int mPid;
3 public int mUid;
4 public String mPackageName;
5
6 TaskInfo () {
7 mPid = -1;
8 mUid = -1;
9 mPackageName = null;
10 }
复制代码
在实现了Parcelable后,就可以跨进程传输了,定义的TaskInfo类:
复制代码
1 public class TaskInfo implements Parcelable {
2 public int mPid;
3 public int mUid;
4 public String mPackageName;
5
6 TaskInfo () {
7 mPid = -1;
8 mUid = -1;
9 mPackgeName = null;
10 }
11 public int describeContents() { //返回值描述Parcel是起什么作用的,一般是0.
12 return 0;
13 }
14
15 public void writeToParcel(Parcel out, int flags) { //用于发送,把需要传输的属性写入Parcel。
16 out.writeInt(mPid);
17 out.writeInf(mUid);
18 out.writeString(mPackageName);
19 }
20
21 public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {//对应writeToParcel(),接收端process会把Parcel object的中间object回复出 ,传递新对象。
22 public TaskInfo createFromParcel(Parcel in) {//初始化 Parcel object
23 return new TaskInfo(in);
24 }
25
26 public TaskInfo[] newArray(int size) {//用于创建多个空对象,使用默认的初始化方法。
27 return new TaskInfo[size];
28 }
29 };
30 private TaskInfo(Parcel in) {//使用Parcel的readInt()、readLong()等方法从Parcel里读出
31 mPid = in.readInt();
32 mUid = in.readInt();
33 mPackageName = in.readString();
34 }
35 }
复制代码