binder机制是android里比较不好理解的东西,网上大部分是长篇大论,新手很难理解,为了能够更好的理解binder机制,方便使用和理解原理,我们需要一步步的去抽丝剥茧。
第一步,先说AIDL 用法
全称是Android Interface Definition Language,即Android接口定义语言。从功能上讲就是android打算跨进程通信。
既然是通信接口,都会有server端和client端。对于开发者而言没有比server端写个java接口,客户端直接取对象实例,直接用啦。嗯,AIDL就是这么干的,不要想复杂,也不要被绕晕。
当然,毕竟要带上跨进程让别人调用的功能,直接写一个普通的interface肯定不行啦,最起码生成真正的java代码的时候是要加点东西的嘛,别着急先梳理AIDL最简单的使用思路。
1、我们需要创建一个基本符合java接口使用习惯的文件。
2、我们Server端要实现这个接口的方法。
3、我们Client端要找到我们想找的对应server端,要到这么个能调用的接口对象。
好,开始。
首先我们在server端通过Android Studio创建一个AIDL文件我是起名叫MyAIDL了(后边也这么称呼了),它的语法和正常接口很类似(毕竟是为了让开发者用的方便),基本类型可以直接用,但毕竟跨进程,想传对象的话需要序列化Parcel,那个后边再说。然后编译一下,我们真正意义上的java接口就出现了,没错就是这么贴心,细看一下这个interface是有嵌套类的,先嵌一个静态类Stub是继承IBinder的,Stub类。里还有个内部类Proxy,Proxy成员变量有个IBinder对象的mRemote,而且这三联套的类都是实现刚才aidl文件要 的接口。这些有印象即可,后边再说。
第二步,我们需要server端嘛,来创建一个Android的四大组件Service,然后Studio会很善意的提醒你需要实现一个onBind方法,要return,回的正是上一步的IBinder,好,直接new MyAIDL.Stub 去实现接口方法。
第三步,Client调用对象。怎么整呢,先把接口java文件拷过来吧,再想得告诉系统用哪个服务,然后取接口对象嘛。做法很简单,Activity中调用bindService传Intent 。然后在连接成功的回调OnServiceConnected中拿到IBinder。注意不要强转,不要强转,不要强转,重要的话说3遍。再回去看下MyAIDL生成的类,Stub里有个asInterface方法。嗯,稳妥的调用替你转成刚才和服务端定的接口了。
好,使用AIDL部分大功告成,是不是很简单~
第二步、想知道原理的咱们继续
毕竟是跨进程通信嘛,没有点系统来帮忙,咱们一个小应用肯定是没能力搞的。那系统是什么呢,没错就是前边看到的那个叫binder的机制,这就从java到c,从应用到内核一大套了,还是那句话,不急慢慢来。
那先从眼前最近的东西开始吧,还记得刚才系统生成的MyAIDL.java三联套对象么。打开再具体看看。
先说咱们调用的asInterface,里边先用传过来的binder调了个queryLocalInterface的方法,嗯,翻译过来叫查询本地接口。查到了就强转返回,没有就new 一个Proxy把binder传进去。顾名思义,本地(也就是当前客户端进程)有就拿缓存了,没有创建个Proxy(代理对象)。
那再看代理对象Proxy类,我们Client端跨进程调用的就是它了,分3部分,两个序列化用的对象_data,_reply,分别作为输入和返回 两个封装。核心是中间那句mRemote.transact后边写着你的方法名的常量的东西。
这里剧透一下,Client端调这个transact 它会调到Server端的Stub下的onTransact下(谷歌命名还是好啊,大家写代码的时候也要好好命名,这样猜都能猜出功能来),然后看Stub下的onTransact,switch咱们的方法名,还是老样子两个Parcel ,data读输入replay做输出,核心是 调this.(你的接口方法)。
this是啥,突然凌乱了么,记住我们还在Stub里(毕竟三联套的类看起来容易乱)?还记得我们之前第二步Server端实现了一个MyAIDL.Stub么,嗯,它成功的调到了我们在Service的onBind里返回的那个对象了。
好,应用部分梳理到这差不多了。总结一下调用Client端的方法->实际是调用一个影子对象Proxy ->Proxy会调用transact将方法名、输入流data、输出流reply等传给 Server端->(系统帮你跨了进程之后)->Service的onBind中return的Stub对象会调用到onTransact方法->调用到你Server端new 出来的Stub对象的真正实现。~完事
第三步、该涉及到系统真正的binder机制跨进程通信啦
看系统一步步方法爬代码很容易晕,没概念的话也容易忘,需要整体有思路,然后一点点去对应就好理解了。先占坑,觉得我我这么讲有意义的话,我再试试生动形象的把binder机制描绘出来。