定义了抽象函数,如上图里的onTransact()函数,成为提供给众多子类别来实现的内部接口。我们以来表示之。
如下图所示:
图3、基类实现CI,并定义
---- 由子类来实现内部接口。Binder基类的很重要目的是支持跨进程调用Service,也就是让远程的Client可以跨进程调用某个Service。Binder基类定义于Binder.java档案里:
// Binder.java
// …….
public class Binder implements IBinder {
// ..........
private int mObject;
public Binder() {
init();
// ...........
}
public final boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
// ................
boolean r = onTransact(code, data, reply, flags);
return r;
}
private boolean execTransact(int code, int dataObj, int replyObj, int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
res = onTransact(code, data, reply, flags);
// ............
return res;
}
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
}
private native final void init();
}
----Binder基类的主要函数是:
transact()函数 --- 用来实作IBinder的transact()函数接口。
execTransact()函数 --- 其角色与transact()函数是相同的,只是这是用来让C/C++本地程序来调用的。
onTransact()函数 --- 这是一个抽象函数,让应用子类来覆写(Override)的。上述的transact()和execTransact()两者都是调用onTransact()函数来实现反向调用(IoC, Inversion of Control)的。
init()函数 --- 这是一个本地(Native)函数,让JNI模块来实现这个函数。Binder()构造函数(Constructor)会调用这个init()本地函数。
如下图:
图4、CI与两个接口的合作
----这个IBinder接口是Binder基类提供给Client的接口,简称为“CI”。于是,Client端调用IBinder接口的transact()函数,透过IPC机制而调用到远方(Remote)的onTransact()函数。
图5、IBinder接口的主要用途:IPC通信
----其实,这个典型的通用性接口设计模式,还有很多种变化的形式。例如下图:
图6、通用性接口设计的变化
----虽然是一个简单的通用性接口设计模式,但是含有丰富的变化机制。例如上图的机制,就让C/C++层的模块成为架构的掌控者。然而,必须理解到:因为设计(和掌控)了IBinder通用性”接口”设计,才能充分保为了C/C++层的模块的”逻辑”控制权。
例如,Android跨进程通信流程,都由底层Binder驱动模块所掌控,如下图所示:
图7、底层Binder驱动模块是IPC的掌控者
2. 通用性接口与Proxy-Stub设计模式
----然而,在上图里的Activity里可能有多个函数,例如f1()和f2()等。于是,在Activity里,必须从f1()函数转而调用IBinder.transact()函数。如果我们在上述架构里面,加上一个Stub类别(如下图的BinderStub类别),它实现了Binder.onTransact()函数,如下图所示:
图8、Stub类将通用性接口转为特殊性接口
----通常,在框架设计里,myProxy和myStub会是成对的,这称为Proxy-Stub模式。如下图所示:
图9、Proxy类将特殊性接口转换到通用性接口
----采用Proxy-Stub设计模式将IBinder接口包装起来,让App与IBinder接口不再产生高度相依性。其将IBinder接口包装起来,转换出更好用的新接口,如下图里的IA接口:
图10、包装IBinder接口,转换出更好用的新接口
----Stub类将onTransact()函数隐藏起来,提供一个更具有美感、更亲切的新接口给subBinder类使用。隐藏了onTransact()函数之后,subBinder类的开发者就不必费心去了解onTransact()函数了。于是,Proxy与Stub两个类遥遥相对,并且将IPC细节知识(例如transact()和onTransact()函数之参数等)包夹起来。由于IBinder接口只提供单一函数(即transact()函数)来进行远距通信,呼叫起来比较不方便。所以Android提供aidl.exe工具来协助产出Proxy和Stub类别,以化解这个困难。只要你善于使用开发环境的工具(如Android的aidl.exe软件工具)自动产生Proxy和Stub类别的程序代码;那就很方便了。 ◆