先看下今天分析的AIDL文件。

点击make project生成的IMyAidlInterface.java文件
1 IMyAidlInterface.java是一个接口,继承了android.os.IInterface。所有Binder通信的接口必须继承IInterface接口

2 Stub静态抽象类继承了Binder类并实现了IMyAidlInterface接口。

在我们Service的回调方法onBind中会返回一个IBinder接口,这里的Stub是继承了Binder类的,而Binder是是实现了IBinder接口的。Stub可以作为我们跨进程通信时,服务端自己需要去实现的。可以继承Stub。

3 DESCRIPTOR: Binder的唯一标识,通常是包名+接口名组成的字符串

4 asInterface :将服务器Binder转换为客户端所需的AIDL接口类型对象。在方法中首先会调用queryLocalInterface(DESCRIPTOR),参数就是binder的唯一标识,用来查询本地接口。如果能查询到本地接口的话(意思就是客户端和服务端处于同一进程),就返回本地接口不进行跨进程通信(节约资源)。如果查询不到本地接口,就构造Proxy代理对象并返回,通过代理对象可以跨进程通信。

5 asBinder()用于返回当前Binder对象

6 Proxy代理类:构造Proxy时,把服务端的Binder对象赋值给mRemote,Proxy中实现了我们自己定义的方法Stringname();通过调用mRemote的transact方法,最后调用到Stub类的onTranct,完成对服务端Binder的调用。

例如iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);这里调用了asInterface方法,把IBinder接口传递进去作为参数,其实也是Binder这个实现类。asInterface里面如上:判断是否是一个进程。这里假设不是同一个进程,就会将这个IBinder赋值给

mRemote,然后当我们调用这个iMyAidlInterface.name()方法值时候,就会通过调用mRemote的transact方法。最后走到Stub的onTransact

7 transact和onTransact方法
(1) 每个AIDL中定义的方法中都有一个int code来标识:

Proxy中实现了name方法,其中会调用到mRemote.transact()方法,transact的第一个参数code是每个方法的唯一标识,客户端远程请求Binder并写入参数,通过transact传入服务端。

(3) onTransact运行在服务端的Binder线程池中,当客户端发起跨进程请求时,请求会通过底层一系列的封装后,交由onTransact处理,服务端通过code来判断客户端请求的方法是什么,接着从data取出目标方法的需要的参数(如果目标方法有参数的话),然后执行目标方法,执行完成后就向replay中写入返回值(如果目标方法有返回值的话),可以看到这个方法时有返回值的,如果返回false,那么代表客户端请求失败。
aidl体现了代理模式的设计思想和CS架构设计(虚拟看作一方当作服务端,一方当作客户端),Proxy是Stub在本地的Clinet代码,服务端需要具体实现Stub,Proxy与Stub依靠transact和onTransact通信,最终完成跨进程的客户端和服务端通信。在这里最后借用网上的图。

网友评论