Binder 机制-AIDL
AIDL 概念
前面我们梳理了 Binder 机制,应该有个概念并且可以简单实现了 Binder 机制入门。
现在试想一下,如果需要定义多个功能服务,每次都要定义服务接口,然后定义 Binder 抽象类,然后定义 Binder 实体类,还有客户端代理类,这些都是重复性的工作。于是 Android 提供了一种 AIDL 文件,通过它可以避免我们做重复性的工作,还能规范 Binder 的具体实现。
在理解为什么叫 AIDL 之前,先了解下 IDL,即接口描述语言。简单来说就是为了不同平台间的系统或程序能进行通信交互而定义的一种规范,只要遵循这套规范,即使是使用不同语言实现,也是可以进行通信的。
what is IDL.png那么再来看 AIDL 就好理解了,就是 Android 为了实现不同进程间的相同通信而约定的规范,所以用 AIDL 可以实现跨进程通信。
AIDL 实现
1.在 src/main 文件夹下右键新建 aidl 文件,AS 会自动创建 aidl 文件夹,并将 aidl 文件都放在这个文件夹内。
2.Rebuild 项目,成功之后会在 build 文件夹内的 generated 文件夹内部找到对应的与 aidl 文件名相同 java 文件。假设,定义一个 IFamilyManager.aidl 编译之后就会生成一个同名的 java 接口,其继承自 IInterface。在接口内部还有一个抽象类 Stub 继承自 Binder 并实现 IFamilyManager 接口,它代表着服务提供方的 Binder 实体,负责注册服务以及从 ServiceManager 中找出相应服务,因为是抽象类,所以其子类或者匿名实例化时肯定要实现接口方法。注意,因为这些方法调用是同步的,所以最好在子线程中执行,确保不会影响主线程,造成 ANR 问题;另外如果有多线程的场景,要主要多线程场景的数据一致性问题。
3.服务方法有了之后,就要将他们暴露出来,以供其他客户端访问,具体实现的方式是通过 Service。客户端可以通过 bindService 的这种形式访问。onBind 方法里返回的就是步骤 2 中的抽象类实例对象。接着再用刚才说的抽象类 Stub 找出服务接口,即调用 asInterface 方法返回 IFamilyManager 类型的引用后,客户端就能和服务端通信了。
回顾一下
和手动实现 Binder 通信相比,AIDL 帮我们做了很多非业务相关的东西,我们需要关心什么(这里主要谈的是作为服务提供方,也就是服务端,对于客户端来说倒没有太大区别),
-
确定需要提供哪些服务,即定义好接口
-
做好各项服务功能的具体实现,并暴露出服务,即定义 Service,以及实现 Stub 实例对象
也就是说用了 AIDL 我们可以只关心业务了,同理,其他的 IDL 作用也是类似的吧。
上面的实现其实可以通过同一个项目工程实现,只要让 Service 在单独的进程中启动就能达到跨进程通信了,但在实际情况中不会这么做,更多的是服务提供方是一个项目工程,客户端一个项目工程。这种情况就类似我们导入第三方库文件一样,通过引入加载的形式,我们才能引用服务方提供的功能。