基于 Handler 的 IPC 进程间通信, android 提供了一种 组件 service, 可以 作为单独的 进程 为 应用程序 提供服务.
大家都知道 handler 是 用来完成 线程间的 通信, 但其实 Handler 提供了 进程间 通信的支持.
一. 先举个 例子:
一. service 端代码为:
在处理 客户端 请求的时候我们 可以看出来 进程 交互的 非 基本数据都被 存储到了 Bundle 中, 因此 如果我们 想传一些 定义的 对象, 可以让这些 对象 实现 Parcelable接口, 以便 放到 Bundle 中 , 进行进程间 交互.
第二点 可以注意的是:当 Service 进程 处理好 请求后, 会 封装好 要返回的数据, 调用 message 的 replyTo 这个 Messenger 对象的 send 方法 把 Service 进程端 封装的 Message 传给 客户端. ( 下面会解释 replyTo 是啥).
二. 客户端 代码又 如下:
1. 创建 ServiceConnection 对象: 通过 onServiceConnected 方法, 我们 创建了 可以向 Service 发 请求的 Messenger 对象 ,其 引用为 server.
2. 于是乎, 我们 可以 调用 server 向 前面提到的 Service 进程 发出请求, 我们 创建一个 Message 消息 把 命令字 赋值给 msg.what, 然后 就可以 调用 server.send() 方法 把 这个 Message 发给 Service 进程处理, 但 如果 Service 进程想 通知 客户端一些 消息 应该怎么处理呢, 所以 我们 传给 Service 进程的消息 要 带上 replyTo 这个值, replyTo 是一个 处理 Service 进程数据返回的 Messenger.
3. 创建 用于 处理 service 进程返回 数据的 Messenger,说白了就是 创建 一个 可以暴漏给 Service 进程 调用的 远程 binder 对象,
二. 再讲一下原理:
概述:
在 Service 端 创建 一个 Messenger 对象, 构造函数的入参为 Handler, 则 在 当前进程 中 创建一个 IMessenger.Stub 对应的 子类 MessengerImpl 的 Binder 对象, 这个 Binder 为 本地Binder. 在 Service 中的 onBinder() 回调方法中 调用 Messenger 对象的 getBinder() 进行返回( 实际上调用的是 MessengerImpl.asBinder() 方法),
在 Client 端中的 ServiceConnection 接口的实现类 中的 onServiceConnected() 方法的第二个参数 为 Service 返回的 代理 Binder, 则 使用 Messenger 构造函数 中 入参为 IBinder 的 创建一个 Messenger 对象, 在 Client 端 创建的 这个 Messenger 是 用来 向 Service 端 发送 Messager 消息的, Messager 消息 对应的 处理 逻辑 是在 Service 端 的 Messenger 对象中的 handleMessage(){} 方法中实现的.
在前面只讲到了 从 Client 端发送 Message 消息 给 Service 端, 但如果 想 通过 Service 端返回 消息 给 Client 端呢, 则 在 Client 端 创建一个 构造函数入参 为 Handler 的 Messenger 对象 delReturn , 然后 将 Client端发给 Service 端 对应的 Message 的 replyTo 字段 赋值为 delReturn 指向的对象, 则 Service 端就可以 通过 Message.replyTo 对应的 Messenger 向 Client端发送 Message.
小结一下 : 通过 Messenger 来 实现 进程间通信的 好处是:
1. 不用烦恼 前后台 约定的 进程间通信协议的变换(aidl文件) , 因为 Messenger 机制里 可以通过 修改 handleMessage() 的实现就可以了,不用修改 远程调用 接口
2. 避免客户端调用 Service 远程 方法 的线程会被阻塞. , Binder机制中 Client端 调用 Service 端 时, Client端对应的线程会等到 Service 端 线程返回才开始继续执行,, 由于 Messenger 在 ipc 通信上 借鉴了 Handler 机制,因此 可以把 方法执行 和方法返回分开 , Messenger 机制下的 client 端 对应的线程 无需 等待 消息 执行完成.
-------------------------------------------------------------------------------------------------------------------------------------------------
1. 首先, 我们看到 IMessenger 对应的 aidl 文件: 可以知道 IMessenger 对应的是 一个 有 send(Message msg) 方法的Binder 对象.
2. 在 Handler.MessengerImpl 类 中 我们可以看到 IMessenger.Stub 本地 binder 端 的代码实现为 : 通过 Handler 的 sendMessage() 方法把 获取到的Message 消息 发给对应的线程的looper中.
3. 在 上面代码截图中, 我们可以看到 Handler 中 有一个 方法 getIMessenger(), 其作用是 返回一个 MessengerImpl() 对象实例. 在使用的时候 我们会 创建 Messenger 对象, 则 从 Messenger 的构造函数中 我们可以看到:
--> Messenger 有 两个构造函数, 其中 一个 入参 为 Handler对象, 则 mTarget 对应的 是 IMessenger aidl 接口 对应的 实体类.
--> 下面是 入参 为 IBinder 对象, 则 target 为 IMessenger aidl 接口 对应的 代理类, 用来 把 消息 Messenger 从当前 进程 发到 IMessenger 对应的 实体类 所在的进程 进行处理: