zoukankan      html  css  js  c++  java
  • Binder机制,从Java到C (4. Parcel)

    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<TaskInfo> CREATOR = new Parcelable.Creator<TaskInfo>() {//对应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 }

     

    3.Parcel的传送

    对于Parcel的传输,我们可以比喻成用传真机來发送一个纸盒子到远方。传真机不是時空传送带,并不会真正可以实现某个物品的跨进程传送,但可以变通來完成:

    (这部分是从网上看到的,但忘了网址是啥了。。)

     这样,传送一个纸盒子就可以分为三个部分了:

    1.把纸盒拆解,得到平面化的图形。
    2.把平面化的图形通过传真及传到远端。
    3.远端的传真机收到平面化的图形后,就可以打印到纸上,再裁剪,粘帖,就可以得到一個一模一样的紙盒子了。

    所以,我們在发送時,可以认为是把对象進行拆解打包,然后塞进Parcel对象里。Parcel就相当于是容器,其中会有一段buffer存放中间结果。这个过程会是通过writeToParcel()方法,将对象的属性拆开,填写到Parcel的buffer中。

    而读取端,会通过某种方法,將Parcel读取出來。

    unflatten操作是通过CREATOR的createFromParcel()來完成。

    4.Parcel支持的数据类型

    Parcel能支持的數據類型有:
      null
      String
      Byte
      Short
      Integer
      Long
      Float
      Double
      Boolean
      String[]
      boolean[]
      byte[]
      int[]
      long[]
      Object[]
      Bundle
      Map
      Parcelable
      Parcelable[]
      CharSequence
      List
      SparseArray
      IBinder
      Serializable

    看,IBinder是可以在进程间传输的!

  • 相关阅读:
    NLog简单配置与使用
    C#将类对象转换为字典
    .net中RSA加密解密
    .net引用System.Data.SQLite操作SQLite
    mongodb的安装以及客户端
    web api 二
    c语言中字符串的存储方式(转)
    cjson两种数组的解析方法(转)
    RT-Thread 自动初始化详解
    RTT与NRF52832移植问题记录
  • 原文地址:https://www.cnblogs.com/zhangxinyan/p/3487856.html
Copyright © 2011-2022 走看看