一、in、out与inout:数据流向与性能
在 AIDL 中,in、out 和 inout 关键字用于控制非基本类型参数的跨进程传递方向。它们的区别主要体现在数据拷贝的次数和客户端对象是否会被修改。
1. in(输入)
- 数据流向:客户端 → 服务端(单向)。
- 底层实现:客户端将数据拷贝到
Binder驱动,驱动再将数据拷贝到服务端。只发生一次数据拷贝。 - 副作用:服务端对参数的修改不会影响客户端的原始对象。
- 使用场景:传递无需服务端修改的输入参数,如查询请求的 ID、用户信息。
2. out(输出)
- 数据流向:服务端 → 客户端(单向)。
- 底层实现:客户端传入的参数会被忽略。服务端需新建对象并填充数据,然后将数据拷贝到
Binder驱动,驱动再将数据拷贝到客户端。 - 副作用:客户端的原始对象会被服务端的修改覆盖。
- 使用场景:从服务端获取新生成的数据,如获取查询结果、生成的用户信息。
3. inout(双向)
- 数据流向:客户端 ↔ 服务端(双向)。
- 底层实现:发生两次数据拷贝,一次从客户端到服务端(输入),另一次从服务端返回到客户端(输出)。
- 副作用:客户端的原始对象会被服务端的修改覆盖。
- 使用场景:需要服务端处理并返回修改后的数据,如对用户信息的更新、状态的同步。
二、oneway:异步调用与线程模型
-
核心作用:
oneway关键字用于标记一个方法为异步调用。客户端调用oneway方法后,会立即返回,不阻塞当前线程。 -
线程模型:
- 客户端:调用
oneway方法时,Binder驱动会立即返回。调用者线程不会被阻塞。 - 服务端:
oneway方法会在一个独立的Binder线程上执行。如果该方法涉及到耗时操作,它不会阻塞服务端的其他Binder线程。
- 客户端:调用
-
使用限制:
oneway方法不能有返回值(必须是void)。oneway方法不能有out或inout参数。
-
使用场景:触发无需即时反馈的操作,如日志记录、数据上报、发送通知等。
三、总结
| 关键字 | 数据方向 | 阻塞类型 | 数据拷贝次数 |
|---|---|---|---|
in | 客户端 → 服务端 | 同步(阻塞客户端) | 一次 |
out | 服务端 → 客户端 | 同步(阻塞客户端) | 一次 |
inout | 客户端 ↔ 服务端 | 同步(阻塞客户端) | 两次 |
oneway | 无返回值 | 异步(不阻塞客户端) | 零或一次 |
通过这些关键字,开发者可以精准控制跨进程通信的数据流向和方法行为,从而优化性能、简化逻辑,并构建出高效、安全的 IPC 机制。