官方文档:http://developer.android.com/guide/components/aidl.html
一、AIDL基本概念
AIDL是Android Interface Definition Language的缩写,目的是有一套规范来实现服务和客户端的互相调用。但是一般来说我们的服务和客户端是存在于不同的进程的(注:是进程Process不是线程Thread)。如果有用过CORBA,COM或者RMI,那对于IDL就不陌生了。
先来复习下,之前的一篇文章有讲过Linux的内存管理模式:
逻辑地址:段地址和位移来进行定位
虚拟地址:每个进程都会有一个用户地址和虚拟地址空间(就是它)
物理地址:代表了真实的RAM,就是大家经常说的几个G内存代表了它的最大寻址空间。
众所周知,进程与进程之间的内存一般来说都不是共享的。这是因为每个进程在建立的时候会向操作系统申请一块内存来保存自己的数据,一旦创建成功这段内存(地址段)就会划归这块内存为该进程独享(虚拟地址段)。每个进程分配的内存都是同一个物理内存里面的一部分,如果进程间需要相互调用或者传递消息,一种方案就是把这部分内存在多个进程中共享,需要就去访问,就叫做IPC(Interprocess Communication)是进程间通信最快的方式。
在Google的官方文档中提到一段关于AIDL的特别说明,这一点我认为非常重要,在开发中需要特别注意。
总结如下:
1. AIDL的调用是方法的调用,这些方法的调用可能存在于不同的线程中(Main thread,Local thread,Remote thread),也就是说可能来自客户端UI线程,本地线程,甚至自己进程中的线程,因此你必须时刻准备应付来自不同线程的调用。
2. 方法的参数有输入(in)输出(out)标签,熟悉C#的人一下就会明白这个直接是语言特性(多返回值),这就代表这个方法的参数是输入还是输出(约等于返回)。
in标记:这个方法的参数如果远程对象状态被改变但是调用方对象状态是不会改变的。
out标记:这个方法的参数如果远程对象状态被改变会影响调用方的对象状态改变。
3. oneway关键字:如果申明这是一个oneway的状态,那么在处理方法的时候不会阻塞,直接将值复制完成之后立即返回。
二、AIDL实现
1. 定义AIDL描述文件:
AIDL的文件以.aidl结尾,通过IDE可以很方便的进行编写,但是IDE不会实时编译这些文件(未实现)。如果要编译这些文件需要手动调用Compile,然后SDK Tools会把你的描述文件生成必要的代码(继承IBinder,实现必要的方法)然后放入gen/目录下。需要注意的是,这些AIDL描述文件必须要客户端和服务端保持一致,也就是说一旦服务端有所修改必须要将这些文件下发给客户端编译使用,不灵活,但是也很无奈。所以在设计AIDL接口的时候一定要注意到可扩展性,倘若有新的功能需要实现,就只好再引入新的AIDL描述文件和接口了。
在AIDL描述文件中可以使用原始类型int, long, float, double, String,如果有复杂对象需要传输则必须实现Parcelable接口,以及List,Map。
2. 服务端接口实例
先来看一段我们现有项目的AIDL描述:
// IWebSocketService.aidl
package com.xingren.service.aidl;
// Declare any non-default types here with import statements
import com.xingren.service.aidl.IWebSocketCallback;
import com.xingren.service.ws