AIDL 基础语法:接口定义、package 声明、import 语句、方法声明
AIDL (Android Interface Definition Language) 是 Android 进程间通信(IPC)的核心契约语言。它使用与 Java 相近的语法定义跨进程接口,编译后生成 Binder 桩代码。本章从最基础的语法单元出发,掌握接口文件的结构、命名空间、依赖引用和方法签名。
1.1 AIDL 文件整体结构
一个标准的 AIDL 接口文件由三部分组成:package 声明(必须)、import 语句(可选)、接口定义与方法声明(必须)。文件扩展名为 .aidl,存放在 src/main/aidl/ 目录下,包路径需与 Java 源码包路径对应。
| 组成部分 | 是否必须 | 作用 |
|---|---|---|
| package 声明 | 是 | 定义接口所属的命名空间,必须与文件所在目录一致 |
| import 语句 | 否 | 引入自定义的 parcelable 类型或其他 AIDL 接口 |
| 接口及方法声明 | 是 | 使用 interface 关键字定义 IPC 契约,内部包含若干抽象方法 |
关键原则:AIDL 只支持声明方法,不支持成员变量或静态常量。所有参数和返回值必须是 AIDL 支持的数据类型(基本类型、String、CharSequence、List、Map、Parcelable、其他 AIDL 接口)。
1.2 package 声明
写法与 Java package 相同,位于文件第一行(忽略注释)。例如:
package com.example.myapp.aidl;
文件必须存放在 src/main/aidl/com/example/myapp/aidl/ 目录下。包名定义后,编译生成的 Java 接口类也会自动放入该包中。
常见错误:package 声明的路径与磁盘目录不一致会导致编译报错
invalid package reference。检查 .aidl 文件的实际目录是否完全匹配 package 声明。
1.3 import 语句
当方法参数或返回值涉及自定义的 Parcelable 类型,或者引用其他 AIDL 接口时,必须使用 import 引入。
import com.example.myapp.model.User;
import com.example.myapp.aidl.ICallback;
如果 Parcelable 类与当前 AIDL 文件在同一包下,import 可省略。系统内置类型(如 String、List、Map)无需 import。
- Parcelable 类:需要同时提供同名
.java文件(实现 Parcelable 接口)和对应.aidl占位声明文件(内容仅为package+parcelable 类名;)。 - AIDL 接口引用:直接引用另一个 AIDL 接口,编译时会自动链接。
1.4 接口定义与方法声明
使用 interface 关键字定义接口,内部声明抽象方法。支持的重载、入参方向标记与基本数据类型如下:
| 语法元素 | 说明 |
|---|---|
interface IMyService { … } | 接口定义,名称建议以 I 开头 |
int add(int a, int b); | 无方向标记(in 为默认) |
void setUser(in User user); | in 方向:数据从客户端流向服务端 |
void getUser(out User user); | out 方向:数据从服务端返回客户端 |
void updateUser(inout User user); | inout 方向:双向传递 |
List<String> getNames(); | 泛型支持,需指定具体类型 |
以下是完整的 AIDL 接口示例:
// IBookManager.aidl
package com.example.library.aidl;
import com.example.library.model.Book;
interface IBookManager {
List<Book> getBookList();
void addBook(in Book book);
void registerCallback(in IOnBookChangeListener listener);
void unregisterCallback(in IOnBookChangeListener listener);
}
调试小技巧:在 AS 中创建
.aidl 文件后,编译一次,即可在 build/generated/source/aidl/debug/ 下看到生成的 Java 桩类(IBookManager.java)。阅读生成的 Stub 与 Proxy 内部类,能加深对 Binder 通信机制的理解。
1.5 AIDL 基础语法关系全景图
下图展示了 AIDL 接口文件从结构到编译产物的整体脉络:
1.6 性能与稳定性注意点
- 方法数量控制:每个 AIDL 接口的方法不宜超过 15 个,过多方法会增加 Binder 事务编号管理的复杂度,且加大维护成本。
- 方向标记影响性能:
in最快(仅序列化一次),out和inout涉及反序列化和回写,会增加拷贝次数。非必要不使用inout。 - 避免大对象传递:1MB 以上数据通过 AIDL 传递会触发 Binder 缓冲区溢出,应改为文件描述符或共享内存。
- 保持接口幂等:跨进程调用可能被重复执行,回调接口应做好去重或状态检查。
实战建议:每次新建 AIDL 接口后,先编译一次确认无语法错误,再编写 Service 端实现。推荐在
build.gradle 中配置 aidl.enableTrace true 可输出更详细的编译日志,便于定位 import 路径问题。