名词解释:
AIDL(Android 接口定义语言): 它允许你在定义在客户端和服务器两端都识别的程序接口,为的是它们可以互相通过 IPC 机制通信。
在 Android 中,一个进程正常情况下不能访问另一个进程的内存。
换句话说,它们需要解析它们的对象成为操作系统能够理解的原始类型,并且为你序列化边界访问对象。
代码的序列化操作编写是很繁琐的,因此 Android 为你用 AIDL 封装了它。
使用 AIDL 的注意事项:
如果你允许通过 IPC 机制访问你的服务的是来自不同的应用客户端,并且需要在你的服务里处理多进程,使用 AIDL 才是有必要的。
如果你不需要执行并发 IPC 访问不同应用,你应该创建实现了 Binder 的自定义接口,或者如果你需要执行 IPC 但是不需要处理多线程,这种情况下,使用 Messenger 实现你的接口。
不管怎样,在实现 AIDL 之前,确保你理解绑定服务(很重要)。
定义你的服务接口时,需要注意:
这些方法可以携带零个或多个参数,有返回值或无返回值。
所有非原始的参数需要有一个指向数据流向的标签显示。可以是
in
,out
, 或inout
当中的某一个。-
原始类型参数默认是
in
,并且不能是其他类型。警告:你应该限制所需要的真实指向,因为序列化参数会带来额外的开销。
在生成的IBinder接口中(import 和 package 语句之前的注释除外)包含了 .adil 文件中所包含的所有代码注释。
只支持方法;你不能在 AIDL 中暴露静态字段。
AIDL 调用过程:
在你开始设计 AIDL 接口之前,要注意 AIDL 接口调用是直接方法调用。你不用假设调用发生在线程中。在本地进程和在远程进程中一个线程调用情况略有不同,具体如下:
- 来自本地进程的调用在发起调用的同一线程内执行。如果该线程是您的主 UI 线程,则该线程继续在 AIDL 接口中执行。 如果该线程是其他线程,则其便是在服务中执行您的代码的线程。 因此,只有在本地线程访问服务时,您才能完全控制哪些线程在服务中执行(但如果真是这种情况,您根本不应该使用 AIDL,而是应该通过实现 Binder 类创建接口)。
- 来自远程进程的调用分派自平台在您的自有进程内部维护的线程池。 您必须为来自未知线程的多次并发传入调用做好准备。 换言之,AIDL 接口的实现必须是完全线程安全实现。
-
oneway
关键字用于修改远程调用的行为。使用该关键字时,远程调用不会阻塞;它只是发送事务数据并立即返回。接口的实现最终接收此调用时,是以正常远程调用形式将其作为来自Binder
线程池的常规调用进行接收。 如果oneway
用于本地调用,则不会有任何影响,调用仍是同步调用。
默认情况下,本地进程下, AIDL 调用是同步的;远程进程下,通过使用关键字 oneway
可以指定 AIDL 为异步调用。