AIDL的in out inout

使用AIDL的第一步是在Service工程中创建一个.aidl文件,并在其中定义ServiceActivity两端统一的AIDL接口:

wKiom1WwovbDRzV-AACWTvXpGd4180.jpg

1

完成定义后,Service工程的gen目录下会立即自动生成IAidl.java文件,此时尚未开始接口函数的具体实现,代码如下:

wKioL1WwpPnzYHd1AAWdmK4SkXo824.jpg

2

wKiom1Wwo1LBMZiiAAQldm8ux-U807.jpg

wKiom1Wwo2ySaHvrAAKXbdRrNAw371.jpg

3

最外层是一个名为IAidl(.aidl文件定义的一致)Interface的定义,它继承了android.os.IInterface

IAidl包含以下两部分:

1、一个名为Stub的抽象子类的定义

2AIDL接口中函数的声明

Stub抽象子类继承了android.os.Binder,并且是IAidl接口的一个实现。Stub中比较重要的三处:

1asInterfac()方法:如31行所示,它的任务是返回一个Proxy子类的对象

2onTransact()方法:IBinder的主要APItransact(),与它对应另一方法是Binder.onTransact()。第一个方法使你可以向远端的IBinder对象发送发出调用,第二个方法使你自己的远程对象能够响应接收到的调用。IBinderAPI都是同步执行的,比如transact()直到对方的Binder.onTransact()方法调用完成后才返回。调用发生在进程内时无疑是这样的,而在进程间时,在IPC的帮助下,也是同样的效果。

3Proxy子类的实现(整个包


含在Stub中,68-107):在Activity连接Service后由Service返回一个IBinder对象,然后由这个对象生成一个Proxy类型的对象(正是调用asInterfac()完成的),赋值给IAidl类型的本地变量,之后可以操作这个IAidl对象调用AIDL接口函数。

wKiom1Wwo8Oz96nqAAGdS0L-T4U211.jpg

4

Proxy子类:

它是Stub类的子类,是本文定义的AIDL接口的一个实现。如图4Service端传入的IBinder对象作为asInterface的输入参数,结合图231行、图37172行可知,此参数最终赋值到了Proxy的本地变量。

Activity端,或者称client端,直接调用的是onServiceConnected的返回值(图430行),然后依此调用AIDL接口函数:

wKiom1Wwo9zACQCtAADs2-qF488517.jpg


5

实际上client端调用的是这个对象是Proxy类型的,调用的函数是Proxy自动生成的,如图3,第85-104行所示,也即图555行的具体实现。看图1,接口函数的参数定义,sourcein,输入型;destinationout,输出型。再看ProxycopyArray的实现,图三中,8889行,新建了两个Parcel对象,_data_reply_data作为传入的参数,_reply为应答。92行:将in型参数source写入_data,完成序列化;96行:写入destination的长度;98行,调用transact()方法,等待ServiceonTransact()响应;onTransact转入第48行执行,5051行创建String[]变量,并从data中反序列化,得到client端传来的String[]变量;53行反序列化,得到int(输出的String[]的长度);59行调用本地的copyArray方法,这时执行的是下面的代码:

wKioL1Wwpc2gAPY8AAGy7KVMROc194.jpg

6

之后62行将输出的String[]_arg1写入Parcelreply变量,完成序列化;此时onTransact执行完毕,返回98行;101行,ProxyonTransact返回的_reply反序列化,写入destination中,destination即获得了返回值。整个流程结束。

如果将AIDL接口函数中,source改为outdestination改为in,代码如下:

对比source---indestination---out时可知,序列化与反序列化过程正好相反。读者可以将两个参数均设为inout,自行查看结果。

总结可知,inoutinout参数使用规则如下:

wKiom1WwpB2x0sUwAADYk6enHBQ016.jpg


wKiom1WwpCqxr-nPAAO4a8jZadI481.jpg

wKiom1WwpGOx3FzoAAK0YiYkjT4071.jpg

inclient端将参数设定好,传给serverserver端拷贝、使用。

outclient将接口、地址等“空壳”传给serverserver将运算结果填充进去,然后client从中取出运算结果。

inoutclient端既从此处传入数据,又从此处取出server填充的结果。

将完成in功能的设成out、或out功能的设成in,都会报错。若将连个均设成inout,则通过,但增加了序列化的步骤,白白浪费运算资源。


你可能感兴趣的:(android,aidl)