oneway

oneway可以用来修饰在interface之前,这样会造成interface内所有的方法都隐式地带上oneway;
oneway也可以修饰在interface里的各个方法之前。
被oneway修饰了的方法不可以有返回值,也不可以有带out或inout的参数。

带oneway的实现

带oneway的方法,不会生成局部变量_reply。且Proxy中transact中第四个参数必为android.os.IBinder.FLAG_ONEWAY

//proxy类@Override public void testOneway(int pa) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(pa);mRemote.transact(Stub.TRANSACTION_testOneway, _data, null, android.os.IBinder.FLAG_ONEWAY);}finally {_data.recycle();}}
//stub类@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{case TRANSACTION_testOneway:{data.enforceInterface(descriptor);int _arg0;_arg0 = data.readInt();this.testOneway(_arg0);return true;}}

不带oneway的实现

不带oneway的方法,会生成局部变量_reply,但当方法返回值为void时,不会生成局部变量_result,这个才是真正的返回值。且Proxy中transact中第四个参数必为0

//proxy类@Override public byte SerTestIn(byte[] pa) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();byte _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeByteArray(pa);mRemote.transact(Stub.TRANSACTION_SerTestIn, _data, _reply, 0);_reply.readException();_result = _reply.readByte();}finally {_reply.recycle();_data.recycle();}return _result;}
//stub类case TRANSACTION_SerTestIn:{data.enforceInterface(descriptor);byte[] _arg0;_arg0 = data.createByteArray();byte _result = this.SerTestIn(_arg0);reply.writeNoException();reply.writeByte(_result);return true;}

in、out、inout参数

为了测试,定义了如下AIDL文件:

package com.java.prac;
import com.java.prac.IListener;interface IService {void registerListener(in IListener listener);void unregisterListener(in IListener listener);byte SerTestIn(in byte[] pa);byte SerTestOut(out byte[] pa);byte SerTestInout(inout byte[] pa);
}

为了方便起见,把proxy类称为调用方,stub类称为实现方。在跨进程调用中,参数和返回值肯定都是会有复制的过程的,由于系统的设计,将内核空间再映射到用户空间,这样复制过程只需要一次。下面代码都是从自动生成的java代码抽取而来。

in参数

//proxy类@Override public byte SerTestIn(byte[] pa) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();byte _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeByteArray(pa);mRemote.transact(Stub.TRANSACTION_SerTestIn, _data, _reply, 0);_reply.readException();_result = _reply.readByte();}finally {_reply.recycle();_data.recycle();}return _result;}
//stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{   ...case TRANSACTION_SerTestIn:{data.enforceInterface(descriptor);byte[] _arg0;_arg0 = data.createByteArray();byte _result = this.SerTestIn(_arg0);reply.writeNoException();reply.writeByte(_result);return true;}...
}
  • proxy调用了_data.writeByteArray(pa);,说明pa这个参数确实传递到了服务方。但stub里只有reply.writeByte(_result);,说明服务方对pa参数的任何改变都不会反应到调用方。

out参数

//proxy类@Override public byte SerTestOut(byte[] pa) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();byte _result;try {_data.writeInterfaceToken(DESCRIPTOR);if ((pa==null)) {_data.writeInt(-1);}else {_data.writeInt(pa.length);}mRemote.transact(Stub.TRANSACTION_SerTestOut, _data, _reply, 0);_reply.readException();_result = _reply.readByte();_reply.readByteArray(pa);}finally {_reply.recycle();_data.recycle();}return _result;}
//stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{   ...case TRANSACTION_SerTestOut:{data.enforceInterface(descriptor);byte[] _arg0;int _arg0_length = data.readInt();if ((_arg0_length<0)) {_arg0 = null;}else {_arg0 = new byte[_arg0_length];}byte _result = this.SerTestOut(_arg0);reply.writeNoException();reply.writeByte(_result);reply.writeByteArray(_arg0);return true;}...
}
  • proxy类里面,发现读取参数的时候,仅仅是_data.writeInt(pa.length);读取一下数组的长度,而不是读取数组的内容。
  • stub类里面,发现它居然用之前读取的数组长度新建了一个数组_arg0 = new byte[_arg0_length];,然后把这个新建的同样长度的数组传递给了真正的方法,难道我们pa参数这个数组的内容都不重要吗,仅仅是为了告诉对方数组的长度吗?(你眉头一皱发现事情并不简单==)事实上,就是这么简单,pa数组的长度才是有用信息。
  • stub类里面,开始设置返回值时,发现多了一步reply.writeByteArray(_arg0);,其实是服务方对新建的数组赋值了,然后要作为返回值返回。
  • proxy类里面,既然服务方要返回调用方一个数组,那就接受吧,_reply.readByteArray(pa);,然后把pa进行赋值。

inout参数

//proxy类@Override public byte SerTestInout(byte[] pa) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();byte _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeByteArray(pa);mRemote.transact(Stub.TRANSACTION_SerTestInout, _data, _reply, 0);_reply.readException();_result = _reply.readByte();_reply.readByteArray(pa);}finally {_reply.recycle();_data.recycle();}return _result;}
//stub类
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{   ...case TRANSACTION_SerTestInout:{data.enforceInterface(descriptor);byte[] _arg0;_arg0 = data.createByteArray();byte _result = this.SerTestInout(_arg0);reply.writeNoException();reply.writeByte(_result);reply.writeByteArray(_arg0);return true;}...
}
  • 分析和上面类似了。
  • 服务方会完好无损地收到调用方发来的pa数组。
  • 服务方可能会对pa数组进行修改,然后再返回给调用方。

总结

  • in参数使得实参顺利传到服务方,但服务方对实参的任何改变,不会反应回调用方。
  • out参数使得实参不会真正传到服务方,只是传一个实参的初始值过去(这里实参只是作为返回值来使用的,这样除了return那里的返回值,还可以返回另外的东西),但服务方对实参的任何改变,在调用结束后会反应回调用方。
  • inout参数则是上面二者的结合,实参会顺利传到服务方,且服务方对实参的任何改变,在调用结束后会反应回调用方。
  • 其实inout,都是相对于服务方。in参数使得实参传到了服务方,所以是in进入了服务方;out参数使得实参在调用结束后从服务方传回给调用方,所以是out从服务方出来。

AIDL oneway 以及in、out、inout参数的理解相关推荐

  1. MySQL 存储过程传参之in, out, inout 参数用法

    存储过程传参:存储过程的括号里,可以声明参数. 语法是 create procedure p([in/out/inout] 参数名  参数类型 ..) in :给参数传入值,定义的参数就得到了值 ou ...

  2. java in out 参数_总是避免Java中的in-out参数?

    毫无疑问,输入输出参数会导致代码混乱,因为它们可能会增加意外/不可预测的副作用. 所以,许多优秀的程序员说: 避免使用in-out参数来更改可变方法参数.希望保持参数不变. 对于一个完美主义程序员来说 ...

  3. mysql 调用存储过程 inout_MySQL存储过程in、out和inout参数示例和总结

    存储过程 1.创建存储过程并查看全局变量 mysql> create database yy; Query OK, 1 row affected (0.00 sec) mysql> use ...

  4. ArcEngine中IFeatureClass.Search(filter, Recycling)方法中Recycling参数的理解

    转自 ArcEngine中IFeatureClass.Search(filter, Recycling)方法中Recycling参数的理解 ArcGIS Engine中总调用IFeatureClass ...

  5. 谈谈对python的理解_浅谈对python pandas中 inplace 参数的理解

    这篇文章主要介绍了对python pandas中 inplace 参数的理解,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧 pandas 中 inplace 参数在很多函数中都会有, ...

  6. uboot加载linux内核加载那些内容,uBoot和Linux内核中涉及到的几个地址参数的理解...

    uBoot和Linux内核中涉及到的几个地址参数的理解 ************************************************* arch/arm/Makefile //内核 ...

  7. 相机的针孔模型及其内参数,外参数的理解

    相机的针孔模型及其内参数,外参数的理解 2019.10.18 FesianXu 文章目录 @[toc] 前言 相机的针孔模型 坐标系的改变 考虑更多因素 总结 更新说明 Reference 前言 在相 ...

  8. Java线程池几个参数的理解

    线程池几个参数的理解: 比如去火车站买票, 有10个售票窗口, 但只有5个窗口对外开放. 那么对外开放的5个窗口称为核心线程数, 而最大线程数是10个窗口.如果5个窗口都被占用, 那么后来的人就必须在 ...

  9. pandas中inplace_对python pandas中 inplace 参数的理解

    pandas 中 inplace 参数在很多函数中都会有,它的作用是:是否在原对象基础上进行修改 inplace = True:不创建新的对象,直接对原始对象进行修改: ​inplace = Fals ...

最新文章

  1. 近期苹果、Facebook等科技巨头股价缘何不断下跌?
  2. linux怎么永久保存,Linux系统中,让alias命令永久保存的方法!
  3. java职业发展路线图_Java程序员如何选择未来的职业路线
  4. init 0-6 这几个启动级别都代表什么意思
  5. python dll load failed_python安装MySQLdb的问题 ImportError: DLL load failed
  6. word关闭首字母自动大写
  7. 凌波多媒体教室软件_看胖瘦终端,如何让教室变得更“智慧”
  8. Unity中实现表格功能
  9. 光猫超级账号密码、宽带账号密码 获取
  10. 海思H.265解码库破解
  11. hdr_pj410说明书_索尼HDR-PJ410
  12. TT 的旅行日记 Week7作业B题
  13. 甘特图(xGantt)项目管理 - 多维企业级
  14. 两片74161实现60进制_用二进制计数器集成芯片74161设计:(1)60进制计数器 (2)6×10进制计数器 (3)10×6进制计数器的实验思路...
  15. 熬粥记:煮一碗红豆粥,3次才领悟煮粥大法
  16. mongoDB之update和save操作
  17. 对lea与mov的理解
  18. 后端开发——Flask框架从入门到入坟(中)
  19. EXCEL Comapre工具使用说明
  20. react中使用echarts的bmap

热门文章

  1. 【lldb】lldb调试时,无法查看变量,查看即crash
  2. python数据分析与挖掘实战-第六章拓展偷漏税用户识别
  3. 简而不凡的“工厂模式”
  4. QQ小程序打开指定QQ群
  5. 黑科技读写内存,修改植物大战僵尸内存值
  6. 教你如何白嫖免费的字体
  7. li 图片错位 浮动_css浮动导致错位怎么解决?
  8. 电磁阀位、通、开/闭原理精髓
  9. A Brilliant Open Letter Song On Piracy To Lily Allen
  10. 微信跳一跳java实现自动跳_微信跳一跳自动连跳挂java源码