Android Binder理解

来源:互联网 发布:amd优化什么意思 编辑:程序博客网 时间:2024/05/18 09:54

Binder使用形式的思考:binder为什么是这样用

Binder是android中很重要的一个概念,书上和网络已经有很多对Binder的说明,往深了有说原理的,浅的则说使用。我没有能力往深里说,因为直到现在其底层原理我也是不明白的。而简单应用层的使用不过进程间通信(IPC),这个形式几乎是固定的,我感觉没什么好说的,aidl,messenger,这些底层都是binder,随便都能找到使用方法。

所以,我这里折中一下,不讲使用的形式,也不分析binder底层,而讲一下binder为什么是这样用的,因为虽然使用的形式是固定的,我们随时能查到,但是理解了为什么是这样,更利于我们使用时能灵活的变化,也不会因为记忆错误而写错代码,更重要的是能缓解那种机械的使用过后的一种迷茫感。理解肯定是好于形式的死记硬背。

对于读者,也就有了两个要求,一,不要追究底层实现;二、对于使用形式是熟悉了的

先简单讲一下我对binder的理解:android系统中用来进程间通信的方式,通过这种方式两个进程间就能互相调用方法,传递对象。我们对于底层的理解就到这里,不去深究为啥这就能通信了。

再说一下使用方式:
进程间通信需要以下3个要素:
1 通信接口:就只是简单的接口,说明服务端能提供什么服务,客户端能使用什么服务。
2 通信接口的binder:我们说了,只有通过binder形式,进程间才能通信,我们必须把接口的实现包装成一个binder才能在进程间传递。
3 接口和binder的转换: 有了接口的binder形式,我们就能把这个接口在进程间传送,但是接收方需要把这个binder转换为接口才能使用

好了,如果对上面的说明觉得可以接受,那就可以往下看了。

我们具体使用的时候是否满足上面的3点要素呢,肯定是满足的,因为我就是根据使用形式抽象出来的3个要素嘛。下面结合起来说明。

具体使用的时候,我们会分以下几步:
1 分别在服务端和客户端声明一个相同的aidl(messenger方式是系统帮你声明了aidl),这就是我们要通信的接口了,但是为什么搞成aidl这副奇怪的模样呢,就是我们今天的主题
2 在服务端搞一个service,这个service只是个形式,重要的是service里面要搞一个实现了功能接口的binder,service的作用只是把这个binder发送出去。service像大炮,里面的binder像炮弹。
3 在客户端也搞一个service用于接收binder,这个service仍然是形式,重要的是接收到的这个binder,接受到后就可以把这个binder解析成接口进行调用了。

这些步骤如何跟3要素对应呢,其实对应的过程都在aidl里面了,它不只是声明了通信接口,它还把接口搞成了binder,它还提供了解析binder为接口的方法。这就是为啥要搞成aidl这个怪样子的原因了。

那么现在重点就落在了aidl身上,搞明白它就完成了今天的任务。

声明了aidl后,sdk会把这个aidl转换成好多东西放到一个.java文件中,简单的可以分为3部分:就是我们的3要素啦

生成的这个java文件分为三层,最外层是一个接口,接口里有个继承了这个接口的内部类,这个内部类里还有个实现了最外层接口的内部类,挺绕的,一层套一层,每层又都继承或实现了相同接口,我一开始是糊涂的。下面把每层拆开来讲。

1 最外层:功能接口:形式跟aidl里面声明的形式差不多,就是一个继承了android.os.IInterface接口的java的接口,增加的函数就是aidl里声明的函数,这就是用来通信的接口了。继承的android.os.IInterface里就一个函数,asBinder,返回一个android.os.InBinder对象,这就是预示了这个接口将来是要被转换为Binder的
2 中间层:stub类,这是一个抽象类,继承了android.os.Binder类和通信接口。它并没有实现通信接口的函数,这里的作用就是把接口包装成一个binder,所以它实现了asBinder函数,返回自己。在service里发射的就是这个类的实例了,它是个抽象类,留下了通信接口的具体实现,而在服务端service发射之前具体实现这个实例。
3 最里层:Proxy类,这个是代理类,负责把收到的binder映射成一个接口,客户端就可以调用了。2中的stub类有个静态方法,asInterface,这个方法就负责返回通信接口,而如果是跨进程调用的话,返回的就是这个Proxy类了,因为这个类也是继承并实现了通信接口的,这个类的构造函数接收一个IBinder,Proxy类不是抽象类,它实现了通信接口的方法,但其实是把方法的实现转给了接收到的Binder的transact方法。而接收到的Binder就是服务端发射的Stub类。这样transact方法就会触发个Stub类的OnTransact方法,OnTransact方法调用具体实现方法。

这样就完成了一个圆圈。还是有点绕吗,再简单的梳理一下。

aidl会生成3个东西,通信接口,通信接口的binder类(Stub),转换通信接口binder类(Stub)到接口实现类的代理类(Proxy)。stub类包装通信接口为binder,proxy类负责转换stub为通信接口。这里stub身兼两职,发射时是binder,接收时要变成接口,这3个是一套,对应关系只有他们内部知道,所以服务端客户端用的同样的aidl,这样才能正确转换嘛。而aidl生成的东西这么绕,原因就是它既要在服务端包装自己,又要在客户端说明自己,是双料间谍,有点自说自话,有点人格分裂,所以绕。

额。。只能讲这么多了

0 0
原创粉丝点击