多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
AIDL是Binder的延伸。一定要先看懂我前面介绍的Binder,再来看AIDL。要按顺序阅读。 Android系统中很多系统服务都是aidl,比如说剪切板。举这个例子,是为了让App开发人员知道AIDL无处不在,和我们距离非常近。 AIDL中需要知道下面几个类: * IBinder * IInterface * Binder * Proxy * Stub 当我们自定义一个aidl文件时(比如MyAidl.aidl,里面有一个sum方法),Android Studio会帮我们生成一个类文件MyAidl.java,如下图所示: ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170516223432791-1010721944.png) MyAidl.java这个生成文件中,包括MyAidl接口,以及Stub和Proxy两个实现了MyAidl接口的类,其中Stub是定义在MyAidl接口中的,而Proxy则定义在Stub类中。 我曾经很不理解,为什么不是生成3个文件,一个接口,两个类,清晰明了。都放在一个文件中,这是导致很多人看不懂AIDL的一个门槛。其实Android这么设计是有道理的。当有多个AIDL类的时候,Stub和Proxy类就会重名,把它们放在各自的AIDL接口中,就必须MyAidl.Stub这样去使用,就区分开了。 对照这张图,我们继续来分析,Stub的sum方法是怎么调用到Proxy的sum方法?然后又调用另一个进程的sum方法的? 起决定意义的是Stub的asInterface方法和onTransact方法。其实这个图没有画全,把完整的Binder Server也画上,就应该是这样: ![](http://images2015.cnblogs.com/blog/13430/201705/13430-20170516223504650-228437964.png) 1)先从Client看起,对于AIDL的使用者,我们这么写程序: MyAidl.Stub.asInterface(某IBinder对象).sum(1, 2); //最好在执行sum方法前判空。 asInterface方法的作用是判断参数——也就是IBinder对象,和自己是否在同一个进程: * 是,则直接转换、直接使用,接下来就跟Binder跨进程通信无关啦; * 否,则把这个IBinder参数包装成一个Proxy对象,这时调用Stub的sum方法,间接调用Proxy的sum方法。 ~~~ return new MyAidl.Stub.Proxy(obj); ~~~ 2)Proxy在自己的sum方法中,会使用Parcelable来准备数据,把函数名称、函数参数都写入_data,让_reply接收函数返回值。最后使用IBinder的transact方法,把数据就传给Binder的Server端了。 ~~~ mRemote.transact(Stub.TRANSACTION_addBook, _data, _reply, 0); //这里的mRemote就是asInterface方法传过来的obj参数 ~~~ 3)Server则是通过onTransact方法接收Client进程传过来的数据,包括函数名称、函数参数,找到对应的函数,这里是sum,把参数喂进去,得到结果,返回。 所以onTransact函数经历了读数据-->执行要调用的函数-->把执行结果再写数据的过程。 下一篇文章要介绍的四大组件的原理,我们都可以对照着AIDL的这张图来看,比如说,四大组件的启动和后续流程,都是在和ActivityManagerService(简称AMS)来来回回的通信,四大组件给AMS发消息,四大组件就是Binder Client,而AMS就是Binder Server;AMS发消息通知四大组件,那么角色就互换。 那么四大组件中,比如说Activity,又是哪个类扮演了Stub的角色,哪个类扮演了Proxy的角色呢?这也是我下一篇文章要介绍的,包括AMS、四大组件各自的运行原理。