在上篇文章《Android多进程通信概述》中,我们对Android中可用的多进程通信技术有一个总体的了解,知道多进程通信的重要性,本文就从最为常用也较为复杂的通信方式Binder开始,了解其机制及用法。
从Service说起
上篇文章提到,AIDL是Service跨进程通信的一种方式,因此也和Service有着不可分割的关系,Service中的 onBind() 方法可以使得Service与其他组件绑定和交互,该方法返回的 IBinder 对象定义了客户端用来与服务进行交互的编程接口,因此,创建提供绑定的服务时,必须提供 IBinder ,用以提供客户端用来和服务进行交互的编程接口。可以通过三种方式来定义接口:Binder,Messenger, AIDL。
扩展 Binder 类
若Service为只在本APP中使用,且与客户端运行在相同的进程下,则可以继承 Binder 类,使客户端通过该类访问服务端Service中的方法。具体步骤如下:
- 在Service中创建Binder扩展类的实例,该实例要满足下列其中一个条件:
- 包含客户端可调用的public方法
- 返回当前Service 实例,其中包含客户端可调用的public方法
- 返回Service包含的其他类的实例,该实例包含客户端可调动的public方法
- 在Service的onBind() 回调方法返回这个Binder扩展类的实例
- 在客户端中,从onServiceConnected() 回调方法中得到 Binder,并通过这个binder使用提供的方法绑定服务
要求服务和客户端必须在同一应用内,是为了便于客户端转换返回的对象和正确调用其 API。服务和客户端还必须在同一进程内,因为此方法不执行任何跨进程编组。
注:在OnBind()方法中需返回一个IBinder实例,不然onServiceConnected方法不会调用。
使用 Messenger
当需要进行进程间通信时,使用 Messenger 比使用 AIDL 更简单,因为 Messenger 会将所有Service调用排入队列,而 AIDL 会同时向 Service 发送多个请求,而Service则必须能够处理多线程。因此,Messenger适用于不需要处理多线程的Service,可以让 Service 一次处理一个调用。具体步骤如下:
- Service 实现一个 Handler,用来接收 client 每个调用的回调
- Service 端用Handler实例创建Messenger对象
- Service 端用 Messenger 创建一个 IBinder,并通过 onBind() 返回到客户端
- Client 端用 IBinder实例化 Messenger(引用Service的Handler实例),并实例化Message发送给Service
- Service 端接收到 Client 发送来的 Message,并在 Handler中接收每个Message进行处理
上述步骤可以实现将Service端对Client发送来的消息进行处理,但如果想让Clinet响应Service发送来的消息,也是可以实现的:在客户端实现一个Messenger,当客户端收到 onServiceConnected() 回调时,会向服务发送一条 Message,可以在该message中设置 replyTo 为客户端Messenger
使用 AIDL
AIDL(Android 接口定义语言)执行将所有对象分解成原语的工作,操作系统可以识别这些原语并将它们编组到各进程中,以执行 IPC。之前采用 Messenger 的方法实际上是以 AIDL 作为其底层结构。Messenger 会在单一线程中创建包含所有客户端请求的队列,以便 Service 一次接收一个请求。 不过,若 Service 要同时处理多个请求,则可直接使用 AIDL,且服务必须具备多线程处理能力,并采用线程安全式设计。
如需直接使用 AIDL,需要创建一个定义编程接口的 .aidl 文件。Android SDK 工具利用该文件生成一个实现接口并处理 IPC 的抽象类,就可以在 Service 内对其进行扩展。
小结
关于 AIDL 的介绍会在单独一篇博文里讲解,且以上关于Binder和Messenger的相关内容都有实现,见github代码,且该代码需要切换分支查看,分支分别为 service-binder
和 service-messenger
网友评论