AIDL 定义的接口文件,使用
in
、
out
、
inout
方向标签表明数据流向:
- 原始类型、String、IBinder 参数以及 AIDL 生成的接口参数 只能 用 in 修饰,可以不显式地写出来。
- 其他类型参数,主要是 Parcel 类型和 List、Map 类型,支持 out、inout,必须显式写出来。
大家只要自己试一下这些参数,并 Build 生成下 Java 文件,就可以发现它们的区别:
- in:Proxy 端流向 Stub 端,Proxy 端将数据写入 Parcel,通过 BinderDriver 后,Stub 端从 Parcel 中读取。
- out:Stub 端流向 Proxy 端,Proxy 端不传递此参数,Stub 端创建实例,执行方法后,将更新后的参数写入 Parcel,Proxy 端从 Parcel 中先读取 Reply,再读取更新后的参数。大家可以类比
来理解。List#toArray(T[])
- inout:Proxy 端写入,Stub 端读取后,执行方法,将更新后的参数传回,Proxy 再读取更新后的参数。大家可以类比
来理解。Arrays#sort(T[])
假设 inout 方向,Proxy 传递
List<String>
[a,b,c],Stub 执行后更新得到 [d,e,f,g],那么最终 Proxy 端读取并更新后 List 的结果就是 [d,e,f,g]。这个过程是通过 Parcle#readStringList 实现的:
public final void readStringList(@NonNull List<String> list) {
int M = list.size(); // 初始 [a,b,c] List
int N = readInt();
int i = 0;
for (; i < M && i < N; i++) {
list.set(i, readString()); // 读取 Parcel 中 Stub 返回的 String 元素: d,e,f,g
}
for (; i<N; i++) {
list.add(readString());
}
for (; i<M; i++) {
list.remove(N);
}
}
参考
- 「Android Binder」AIDL中的 in / out 到底是啥?