疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Binder机制从Java到 C


 

  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 }