好久没写bolg,又一个新的学期,这次写一篇关于android进程间通信的总结。

android进程间通信的方式

  1. 通过共享文件实现
  2. 通过AIDL
  3. 通过Binder
  4. 通过Handler messenger机制
  5. 通过ContentProvicer
  6. 通过Socket

基本上安卓上的进程间通信就以上几种,需要说明的是,2,4,5都是基于Binder实现的。 而他们的优缺点分别是:

名称优点缺点应用场景Bundle简单易用只能传输Bundle支持的数据类型四大组件的进程间通信文件共享简单易用不适合高并发场景,无法做到进程间的及时通信没有并发的情形,交换简单的数据AIDL功能强大,支持一对多的并发通信,支持实时通信使用稍复杂,需要处理好线程同步一对多通信且有RPC需求Messager功能一般,支持一对多的串行通信,支持实时通信不能很好处理并发现象,并不支持RPC,只能传输Bundle支持的数据类型低并发的一对多即时通信,无RPC需求ContentProvider数据访问方面功能强大,支持一对多并发数据共享收约束的AIDL,主要提供数据源的CRUD操作一对多的进程间数据共享Socket功能强大,可通过网络传输字节流,支持一对多的并发实时通信繁琐,不支持直接的RPC网络数据交换

RPC:Remote Procedure Call (远程过程调用) 调用另一台计算机上的程序。


文件

这个就不说了,就是不同进程读写相同的文件,不过要注意避免同时写,在写的时候加锁。

AIDL

AIDL 全程Android Interface Define Language 是Android 提供的一种进程间通信(IPC)机制,可以用它定义客户端和服务端进程间通信时候的接口,它包装了Binder的使用,通过这种机制,我们只需要写好AIDL接口文件,编译时系统会帮我们生成Binder接口。

Binder支持的4种数据:

  1. Java的基本数据类型
  2. List和Map(元素必须是AIDL支持的数据类型,Server端具体的类必须是ArrayList或者HashMap)
  3. 其他AIDL生成的接口
  4. 实现Parcelable的实体,

AIDL 的编写主要为以下三部分:

创建 AIDL 创建要操作的实体类,实现 Parcelable 接口,以便序列化/反序列化 新建 aidl 文件夹,在其中创建接口 aidl 文件以及实体类的映射 aidl 文件 Make project ,生成 Binder 的 Java 文件 服务端 创建 Service,在其中创建上面生成的 Binder 对象实例,实现接口定义的方法 在 onBind() 中返回 客户端 实现 ServiceConnection 接口,在其中拿到 AIDL 类 bindService() 调用 AIDL 类中定义好的操作请求

自动生成的java文件继承了IInterface,而且还包含一个抽象类Stub,是一个Binder,实现AIDL接口。 IInterface 类型的接口,包括: Stub 抽象类 aidl 接口定义的操作方法 Stub ,是一个 Binder,同时也是一个 IInterface,包括: 将 Binder 转成 IInterface 的 asInterfa 大专栏 andorid进程通信ce() 方法 处理调度的 onTransact() 方法 用于在 onTransact() 中标识要进行的操作的两个标志 一个 IInterface 类型的代理 Proxy, IInterface 类型的代理,包括: 接口定义方法的伪实现,实际调用的是真正的 Binder 的方法

Binder机制

Binder继承自IBinder,IBinder是一个接口,代表跨进程传输的能力。(IBinder 是高性能、轻量级远程调用机制的核心部分,它定义了远程操作对象的基本接口。)

在Binder机制中Client发起IPC请求时会将请求数据从用户空间拷贝到内核空间(在Binder驱动的帮助下),驱动程序再将内核空间中的数据写到Service中。而ServerManager负责Service的注册和查询。

Messenger

Messenger 的使用需要结合 Handler, Message, Bundle 。 创建客户端的 Messenger,传递一个 Handler 处理消息 bindService,在 ServiceConnection 回调中拿到服务端的 Messenger 发送消息 Message.obtain() 消息池里获取一个空闲消息对象 使用 message.setData(bundle) 设置数据 指定回信的信使 message.replyTo = mClientMessenger 调用服务端信使,发射!mServerMessenger.send(message)

Messenger 对 AIDL 进行了封装,也就是对 Binder 的封装,我们可以使用它的实现来完成基于消息的跨进程通信,就和使用 Handler 一样简单。

ContentProvider

主要方法: onCreate():初始化 provider query():查询数据 insert():插入数据到 provider update():更新 provider 的数据 delete():删除 provider 中的数据 getType():返回 provider 中的数据的 MIME 类型

ContentProvider可以提供多种不同的数据类型: int long double float BLOB:作为 64KB 字节的数组的二进制大型对象

Socket

TCP 或者 UDP 的报文中,除了数据本身还包含了包的信息,比如目的地址和端口,包的源地址和端口,以及其他附加校验信息。 由于包的长度有限,在传输的过程中还需要拆包,到达目的地后再重新组合。 如果有丢失或者损坏的包还需要重传,有的在到达目的地后还需要重新排序。 这些工作是复杂且与业务无关的,Socket 为我们封装了这些处理工作。 Socket 被称为“套接字”,它把复杂的 TCP/IP 协议簇隐藏在背后,为用户提供简单的客户端到服务端接口,让我们感觉这边输入数据,那边就直接收到了数据,像一个“管道”一样。

使用 TCP 通信的 Socket 流程 服务端: 调用 ServerSocket(int port) 创建一个 ServerSocket,绑定到指定端口 调用 accept() 监听连接请求,如果客户端请求连接则接受,返回通信套接字 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发 关闭套接字 客户端: 调用 Socket() 创建一个流套接字,连接到服务端 调用 Socket 类的 getOutputStream() 和 getInputStream() 获取输出和输入流,进行网络数据的收发 关闭套接字

使用 UDP 通信的 Socket 流程 服务端: 调用 DatagramSocket(int port) 创建一个数据报套接字,绑定到指定端口 调用 DatagramPacket(byte[] buf, int length) 建立一个字节数组,以接受 UDP 包 调用 DatagramSocket 的 receive() 接收 UDP 包 调用 DatagramSocket.send() 发送 UDP 包 关闭数据报套接字 客户端: 调用 DatagramSocket() 创建一个数据报套接字 调用 DatagramPacket(byte buf[], int offset, int length,InetAddress address, int port) 建立要发送的 UDP 包 调用 DatagramSocket 的 receive() 接收 UDP 包 调用 DatagramSocket.send() 发送 UDP 包 关闭数据报套接字

标签: 接字, 进程, Socket, 通信, 调用, 接口, AIDL, Binder, andorid

相关文章推荐

添加新评论,含*的栏目为必填