Android进程间通讯-AIDL实现原理

Android进程间通讯基于Proxy(代理)与Stub(桩或存根)的设计模式(如图1-1所示)。其中,Proxy将特殊性接口转换成通用性接口,Stub将通用性接口转换成特殊性接口,两者之间的数据转换经过Parcel(打包)进行的,Proxy常做为数据发送代理,经过Parcel将数据打包发送,Stub常做为数据接收桩,解包并解析Parcel Data package。Android进程间通讯就是经过这样的 “代理-桩” 的设计模式运做的。java

                                                           图 1-1设计模式

关于Proxy与Stub注意:gradle

  1. Stub 跟 Proxy 是一对,俗称“代理-桩”,通常用在远程方法调用。
  2. Proxy 至关因而拿在手里的遥控器,而 Stub 至关于长在电视机里的遥控接收器,它们有着一一对应的接口方法,但操做的方向恰好相反。
  3. Proxy 的接口供客户端程序调用,而后它内部会把信息包装好,以某种方式(好比 RMI)传递给 Stub,然后者经过对应的接口做用于服务端系统,从而完成了“远程调用”。
  4. 通常不一样进程间通讯的时候都会用到这种模式。
  5. 关于Stub的asInterface(Binder), 能够返回Stub或Stub.Proxy(若是客户端和服务端在同一个进程下,那么asInterface()将返回Stub对象自己,不然返回Stub.Proxy对象)。咱们都知道,Binder的工做机制客户端,Binder,服务端组成的,客户端和服务端都是经过Binder来交流的(Binder也是Android中一个java类)。AIDL生成的java代码中,Stub类是继承于Binder类的,也就是说Stub实例就是Binder实例。
  6. Stub和Stub.Proxy的区别:(1)若是在同一个进程下的话,那么asInterface()将返回服务端的Stub对象自己,由于此时根本不须要跨进称通讯,那么直接调用Stub对象的接口就能够了,返回的实现就是服务端的Stub实现,也就是根本没有跨进程通讯;(2)若是不是同一个进程,那么asInterface()返回是Stub.Proxy对象,该对象持有着远程的Binder引用,由于如今须要跨进程通讯,因此若是调用Stub.Proxy的接口的话,那么它们都将是IPC调用,它会经过调用transact方法去与服务端通讯。

关于AIDL定义以及实现流程图:编码

AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言。咱们在写完AIDL文件后,编译器会帮咱们自动生成一个同名的 .java 文件(在gen相应目录下)。在服务端和客户端中也能够照常使用这个 .java 类来进行跨进程通讯。spa

关于Proxy类几个对象及方法(客户端最终经过这个Proxy类与服务端进行通讯).net

    • 关于 _data_reply 对象:通常来讲,咱们会将方法的传参的数据存入_data 中,而将方法的返回值的数据存入 _reply 中—在没涉及定向 tag 的状况下。若是涉及了定向 tag ,状况将会变得稍微复杂些,具体是怎么回事请参见这篇博文:你真的理解AIDL中的in,out,inout么?
    • 关于 Parcel :简单的来讲,Parcel 是一个用来存放和读取数据的容器。咱们能够用它来进行客户端和服务端之间的数据传输,固然,它能传输的只能是可序列化的数据。具体 Parcel 的使用方法和相关原理能够参见这篇文章:Android中Parcel的分析以及使用
    • 关于 transact() 方法:这是客户端和服务端通讯的核心方法。调用这个方法以后,客户端将会挂起当前线程,等候服务端执行完相关任务后通知并接收返回的 _reply 数据流。关于这个方法的传参,这里有两点须要说明的地方: 
      • 方法 ID :transact() 方法的第一个参数是一个方法 ID ,这个是客户端与服务端约定好的给方法的编码,彼此一一对应。在AIDL文件转化为 .java 文件的时候,系统将会自动给AIDL文件里面的每个方法自动分配一个方法 ID。
      • 第四个参数:transact() 方法的第四个参数是一个 int 值,它的做用是设置进行 IPC 的模式,为 0 表示数据能够双向流通,即 _reply 流能够正常的携带数据回来,若是为 1 的话那么数据将只能单向流通,从服务端回来的 _reply 流将不携带任何数据。 
        注:AIDL生成的 .java 文件的这个参数均为 0。

关于客户端通常的工做流程:线程

  • 1,生成 _data 和 _reply 数据流,并向 _data 中存入客户端的数据。
  • 2,经过 transact() 方法将它们传递给服务端,并请求服务端调用指定方法。
  • 3,接收 _reply 数据流,并从中取出服务端传回来的数据。

关于服务端的通常工做流程:设计

  • 1,获取客户端传过来的数据,根据方法 ID 执行相应操做。
  • 2,将传过来的数据取出来,调用本地写好的对应方法。
  • 3,将须要回传的数据写入 reply 流,传回客户端。

关于Android中AIDL的简单例子,参加以下Demo:代理

https://blog.csdn.net/jingwen3699/article/details/53400288对象

(注意:在Android Studio中,客户端和服务端的AIDL接口文件所在的包未必相同,最好在gradle中配置路径!)

 

其它参考连接:

https://blog.csdn.net/scnuxisan225/article/details/49970217 

https://blog.csdn.net/a910626/article/details/51173668

https://blog.csdn.net/luoyanglizi/article/details/52029091 (详细原理来分析,good)

相关文章
相关标签/搜索