今天在学习任主席的Android艺术开发探索时学习到了Binder,特此在本文中做一下对于Binder的总结。
首先我们为什么会使用Binder呢?
在Android系统当中,进程与进程是不可以进行直接访问的,这保证了Android进程的独立性(比如一个APP崩掉了,不会导致所有APP崩掉),同时也保证了Android进程的安全性。
但是Andorid系统进程间不可以直接进行通讯,那么我们要如何实现通讯呢?
我们可以通过Android系统底层来实现间接的进程间通讯,而这时通讯的信使,就是Binder了。通讯过程如下图
虽然在日常开发中,我们可以通过AIDL来快速的编译出一个Binder类,但是为了更好的学习我们还是要打开Binder类去分析它的?下表会列出Binder的主要组成的方法以及内部类。
DESCRIPTOR常量 | asBinder方法 | onTransact方法 | Proxy代理内部类 | asInterface方法 |
Binder如上表所述,一个继承了Binder的子类需要至少实现上面4个才可以进行进程间通信,下面来简单的描述一下这5个都具体做了哪些操作 |
---|
DESCRIPTOR
它是Binder的唯一标识符,一般会设置为包名+类名,用于指定Binder类,一般我们使用一个静态的String常量。
asInterface
用于将服务端的Binder转换为客户端所需要的AIDL接口类型的对象,这个转换是区分进程的,如果客户端和服务端位于同一个进程当中,那么就会返回服务端的Stub对象本身,反之返回Stub.proxy对象。
asBinder
这个方法返回当前的Binder对象
onTransact
该方法运行在服务端中的Binder线程池中,当客户端发起跨进程请求的时候远程请求会通过系统底层封装后交由此方法来处理。
rotected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException
从上述代码可以看出该方法有四个参数,code参数可以确定客户端具体的请求是什么,data就是去除目标方法所需要的参数如果没有就不执行,当目标代码执行完毕,就会将返回值写入在reply当中没有返回值就不会执行,如果此方法返回了false,那么客户端就会请求失败,我们可以利用这样的机制来过滤进程。
proxy
这是一个内部类,他实现了我们的接口,他创建了接口方法所需要的输入性Parcel对象,输出型Parcel对象,和返回值对象,然后把该方法的参数信息写入输入型对象里,在调用transact方法来发起RPC请求,同时线程会被挂起,服务端onTransact方法会被调用,直到RPC过程返回后,才继续执行线程,并且从输出型Parcel对象去除RPC对象返回的结果。
下面我们就手动来实现一个Binder的服务类:要做的有3部操作。(我这里使用的是任主席的例子)
1.实现继承了IInterface接口的接口。
2.在接口中实现Stub类。
3.实现继承了Binder的子类,并实现2的接口。
首先我们来实现接口并且实现Stub类。代码如下(不懂得地方可以看注释,注释写的很详细):
public interface IBookManager extends IInterface { //新建Stub类 public static abstract class Stub extends Binder implements IBookManager { List<Book> mBookList = new ArrayList<>(); private final IBookManager.Stub mBinder = new IBookManager.Stub(){ @Override //返回当前Binder public IBinder asBinder() { return mBinder; } @Override //返回书 public List<Book> getBookList() throws RemoteException {