概念
AIDL是Android Interface Definition Language的简写,即Android接口定义语言。我们知道Android系统为每一个应用开启一个独立的虚拟机,每个应用都运行在各自进程里(默认情况下),彼此之间相互独立,无法共享内存。当一个应用想要访问另一个应用的数据或调用其方法,就要用到Android系统提供的IPC机制。而AIDL就是Android实现IPC机制的方式之一
除了AIDL,Android还提供了Messenger来实现跨进程通信,不过Messenger是以单线程串行方式(消息队列)来处理来自不同客户端的访问的,并不适合多线程并发访问。当需要提供跨进程以及多线程并发服务时就需要AIDL上场了。
// Messenger实际上也是以AIDL作为其底层结构。
使用
1.创建AIDL
我们在对应的src的Package下创建一个AIDL文件(Android Studio->File->New->AIDL->AIDL file),创建后Android Studio会自动把这个.aidl文件放到一个aidl的目录下。
basicTypes方法中给我们展示了AIDL支持的基本数据类型,除此之外,AIDL还支持:CharSequence, List & Map(List和Map中的所有元素都必须是AIDL支持的数据类型、其他AIDL生成的接口或您声明的可打包类型。)
2.Step2. 创建一个Service暴露AIDL接口并实现AIDL的接口函数
通过bindService绑定这个服务,即可以获得AIDL的接口调用的引用。运行前,我们设置一下AndroidManifest.xml文件记这个Service运行在一个单独的进程中:
<service
android:name=".RemoteService"
android:process=":remote"
android:enabled="true"
android:exported="true"/>
现在来bindService:
运行之后,就能拿到服务里的返回结果
到这里,我们完成了一个AIDL的范例,有几个地方可能会对我们造成困扰:
Stub类:Binder的实现类,服务端需要实现这个类来提供服务。
asInterface函数: 一个静态函数,用来将IBinder转换成对应的Binder的引用。先通过queryLocalInterface查询,如果服务端和客户端都是在同一个进程,那么就不需要跨进程了,直接将IRemoteService当做普通的对象来使用,否则会返回远程对象的代理对象(Proxy)。
这里aidl创建的时候已经帮我们实现好了,其实这里也可以自己实现下stub类和asinterfacr函数
in、out和inout表示数据的流向。大家可以把AIDL的客户端和服务端理解成两个进程(其实大多数情况也是这样才会使用AIDL),从客户端流向服务端用in表示,表示这个对象是从客户端中传递到服务端,在服务端修改这个对象不会对客户端输入的对象产生影响。
而out则表示,数据只能从服务端影响客户端,即客户端输入这个参数时,服务端并不能获取到客户端的具体实例中的数据,而是生成一个默认数据,但是服务端对这个默认数据的修改会影响到客户端的这个类对象实例发生相应的改变。
理解了in、out之后,inout自然不需要再解释了。AIDL默认支持的数据类型使用in修饰符,对于我们自定义的Parcelable对象,一般情况下我们也是使用in,如果没有必要,应该尽量避免inout。
Intent也是Parcelable实现
也许你会想到,我们在Activity间可以通过Intent携带参数,其实你去看的源码的话会发现Intent也是一个Parcelable的实现类,而且在系统的工程中也有一个Intent.aidl文件(路径:/frameworks/base/core/java/android/content/Intent.aidl)。所以,它才可以在进程间传递。
参考https://www.jianshu.com/p/467016b4487c