Binder连接池
2016-06-09 13:07
453 查看
Binder连接池
首先回顾一下 AIDL 的 大致流程:首先创建一个Service和一个AIDL接口,接着创建一个类继承自AIDL接口中的Stub类并实现Stub中的抽象方法,在Service的onBind方法中返回这个类的对象,然后客户端就可以绑定Service,建立连接就可以访问远程服务端的方法了。如果有100个地方需要用到 AIDL ,需要创建100个 Service 吗?
答案是显而易见的,这时我们需要将AIDL放在同一个Service中去管理。
在这种模式下,整个工作机制是这样的:每个业务模块创建自己的 AIDL 接口并实现此接口,这个时候不同业务模块之间是不能有耦合的,所有的实现细节需要单独开来,然后向服务端提供一个唯一标识和其对应的 Binder 对象; 对于服务端来说,只需要一个 Service 就可以了,服务端提供一个 queryBinder 接口,这个接口会返回相应的 Binder对象。Binder 连接池的主要作用就是将每个业务模块的 Binder 请求统一转发到远程 Service 中去执行,从而避免了重复创建Service工程。下面看一个简单的例子
1.提供两个 AIDL 接口 :ISecurityCenter 和 ICompute
// ISecurityCenter.aidl interface ISecurityCenter { String encrypt(String content); String decrypt(String password); }
// ICompute.aidl interface ICompute { int add(int a,int b); }
2.实现这两个接口
public class SecurityCenterIml extends ISecurityCenter.Stub { private static final char SECRET_CODE = '^'; @Override public String encrypt(String content) throws RemoteException { char[] chars = content.toCharArray(); for (int i = 0; i < chars.length; i++) { chars[i] ^= SECRET_CODE; } return new String(chars); } @Override public String decrypt(String password) throws RemoteException { return encrypt(password); } }
public class ComputeIml extends ICompute.Stub{ @Override public int add(int a, int b) throws RemoteException { return a + b; } }
3.为 Binder 连接池创建AIDL接口 IBinderPool.aidl
// IBinderPoll.aidl interface IBinderPool { IBinder queryBinder(int binderCode); }
4.为Binder连接池创建远程Service并实现IBinderPool
@Override public IBinder queryBinder(int binderCode) throws RemoteException { IBinder binder = null; switch (binderCode) { case BINDER_SECURITY_CENTER: binder = new SecurityCenterIml(); break; case BINDER_COMPUTE: binder = new ComputeIml(); break; default: break; } return binder; } }
当Binder连接池连接上远程服务时,会根据不同模块的标识即binderCode返回不同的Binder对象,通过这个Binder对象所执行的操作全部发生在远程服务端。
5.Service 的实现比较简单
public class BinderPoolService extends Service { private static final String TAG = "BinderPoolService"; private Binder mBinderPool = new BinderPool.BinderPoolImpl(); @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind"); return mBinderPool; } @Override public void onDestroy() { super.onDestroy(); } }
6.Binder连接池内部需要去绑定远程服务,绑定成功后服务端就可以通过它的queryBinder方法去获取对应的Binder。
public class BinderPool {
public static final int BINDER_SECURITY_CENTER = 1;
public static final int BINDER_NONE = -1;
public static final int BINDER_COMPUTE = 0;
private Context mContext;
private IBinderPool mBinderPool;
private static volatile BinderPool sInstance;
private CountDownLatch mConnectBinderPoolCountDownLatch;
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient,0);
mBinderPool = null;
connectBinderPoolService();
}
};
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
mBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
}
mConnectBinderPoolCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private BinderPool(Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}
private synchronized void connectBinderPoolService() {
mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
Intent intent = new Intent(mContext,BinderPoolService.class);
mContext.bindService(intent,mBinderPoolConnection,Context.BIND_AUTO_CREATE);
try {
mConnectBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public IBinder queryBinder(int bindService){
IBinder binder = null;
if (mBinderPool != null){
try {
binder = mBinderPool.queryBinder(bindService);
} catch (RemoteException e) {
e.printStackTrace();
}
}
return binder;
}
public static BinderPool getsInstance(Context context) {
if (sInstance == null) {
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
public static class BinderPoolIml extends IBinderPool.Stub {
@Override public IBinder queryBinder(int binderCode) throws RemoteException { IBinder binder = null; switch (binderCode) { case BINDER_SECURITY_CENTER: binder = new SecurityCenterIml(); break; case BINDER_COMPUTE: binder = new ComputeIml(); break; default: break; } return binder; } }
}
7.客户端代码
public class BinderPoolActivity extends AppCompatActivity { private ISecurityCenter mSecurityCenter; private ICompute mCompute; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_binder_pool); new Thread(new Runnable() { @Override public void run() { doWork(); } }).start(); } private void doWork() { BinderPool binderPool = BinderPool.getsInstance(BinderPoolActivity.this); IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER); mSecurityCenter = SecurityCenterIml.asInterface(securityBinder); String msg = "Hello 安卓"; try { String password = mSecurityCenter.encrypt(msg); Logger.i("encrypt:" + password); Logger.i("decrypt:" + mSecurityCenter.decrypt(password)); } catch (RemoteException e) { e.printStackTrace(); } IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE); mCompute = ComputeIml.asInterface(computeBinder); try { Logger.i("add 3 + 5 :" + mCompute.add(3, 5) + ""); } catch (RemoteException e) { e.printStackTrace(); } } }
Log
╔════════════════════════════════════════════════════════════════════════════════════════ ║ Thread: Thread-245 ╟──────────────────────────────────────────────────────────────────────────────────────── ║ BinderPoolActivity.access$000 (BinderPoolActivity.java:11) ║ BinderPoolActivity.doWork (BinderPoolActivity.java:39) ╟──────────────────────────────────────────────────────────────────────────────────────── ║ encrypt:;221~寗匍 ╚════════════════════════════════════════════════════════════════════════════════════════ ╔════════════════════════════════════════════════════════════════════════════════════════ ║ Thread: Thread-245 ╟──────────────────────────────────────────────────────────────────────────────────────── ║ ║ BinderPoolActivity.doWork (BinderPoolActivity.java:40) ╟──────────────────────────────────────────────────────────────────────────────────────── ║ decrypt:Hello 安卓 ╚════════════════════════════════════════════════════════════════════════════════════════ ╔════════════════════════════════════════════════════════════════════════════════════════ ║ Thread: Thread-245 ╟──────────────────────────────────────────────────────────────────────────────────────── ║ BinderPoolActivity.access$000 (BinderPoolActivity.java:11) ║ BinderPoolActivity.doWork (BinderPoolActivity.java:49) ╟──────────────────────────────────────────────────────────────────────────────────────── ║ add 3 + 5 :8 ╚════════════════════════════════════════════════════════════════════════════════════════
这样如果有新业务需要加新的 AIDL ,那么实现它自己的 AIDL 接口后,只需要修改 BinderPoolIml 中的 queryBinder 方法,给自己添加一个新的 binderCode 并返回对应的 Binder 对象即可。
另一张表格来说明如何选择合适的 IPC 方式
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories