AIDL 中支持哪些数据类型?如何传递自定义 Parcelable 对象?
解读
国内面试中,这道题几乎 100% 出现在“Framework / 进程通信”环节,面试官想确认三件事:
- 你对 Binder 内核层只认 Parcel 这件事是否心里有数;
- 你是否真的写过跨进程代码,还是只会背八股;
- 遇到“自定义对象”时,你能否把 Java 层、AIDL 语法、C++ Parcel 三端对齐,不出 SecurityException / BadParcelableException。
回答时先给出“官方清单”,再补一句“为什么只能传这些”,最后把 Parcelable 的完整链路(aidl → java → CREATOR → 注册)拆成 4 步讲清楚,就能拿到高分。
知识点
- AIDL 语言层面支持的 7 大原生类型:byte、int、long、float、double、boolean、char(String/CharSequence 算特殊引用)。
- 容器类只允许 ArrayList<T>,且 T 必须是 1、3、4 点中的类型;Map 不支持,HashMap 想传请转 ArrayList<key-value 包裹类>。
- Parcelable 接口是 Binder 内核唯一认可的“自定义对象”序列化协议,Serializable 在 AIDL 里无效。
- AIDL 编译器生成 Stub/Proxy 时,会把 Parcelable 变量拆成两个函数调用:writeParcelable / readParcelable,底层对应 Parcel.cpp 的 writeStrongBinder 与 readStrongBinder。
- 跨进程传递时,系统会在内核态做一次 memcpy,用户态只认 CREATOR,因此 CREATOR 必须是 public static final,且类名与 aidl 中 import 路径完全一致,否则运行期抛 BadParcelableException。
- 国内 ROM 常见坑:华为/小米对 SELinux 权限裁剪较多,如果 Parcelable 类放在非 exported 的 apk 中,另一条进程可能拿不到 ClassLoader,需显式 setExtrasClassLoader()。
- 版本兼容:Android 13 后 T 端强化 Parcel 的“buffer 只读”标记,writeToParcel 里若修改已写入的字段会触发 IllegalStateException,面试时主动提一句“只读拷贝”能体现你对源码的跟进。
答案
AIDL 支持的数据类型分四档:
- Java 原生基本类型:byte、int、long、float、double、boolean、char;
- String、CharSequence;
- 实现了 Parcelable 的自定义对象;
- 由 1、3 构成的 ArrayList,以及 Parcelable 的 ArrayList(List<MyBean> 写法语法糖,编译后仍是 ArrayList)。
传递自定义 Parcelable 对象需四步:
- 定义 Bean 类并实现 Parcelable,补全 writeToParcel、describeContents、protected 构造器、public static final CREATOR;
- 在与 IXXService.aidl 同目录下新建 Bean.aidl,内容只有两行: package com.xx.bean; parcelable Bean;
- 在业务 aidl 接口中 import 上述 Bean,方法签名里直接写 in Bean data(或 out、inout,按业务选方向);
- Client/Server 两端保持 Bean 类包名、类名、序列化顺序完全一致,且在读取端调用 setExtrasClassLoader(getClassLoader()) 防止 ClassNotFoundException。
拓展思考
-
为什么 AIDL 不支持 Serializable?
Serializable 使用反射,产生大量临时对象,GC 抖动在 16 ms 帧率下容易掉帧;而 Parcelable 是手工顺序读写,速度比 Serializable 快 10 倍以上,符合 Binder 1MB 缓冲区高并发场景。 -
跨 APP 传递大列表怎样防止 TransactionTooLargeException?
国内主流做法是分页 + SharedMemory:先传一个 fd 到对端,再 mmap 读数据,既避开 1 MB 硬性限制,又减少一次拷贝;面试时能把“fd 序列化”和 ParcelFileDescriptor.dup() 讲清楚,可再拿一分。 -
Kotlin 化后是否还需要手写 Parcelable?
官方 @Parcelize 插件已稳定,但国内银行、证券类 App 因合规要求禁用 kapt,只能回退手写;提前调研客户场景,能体现你的落地意识。