线程池机制
核心思路
在 Android 开发中,当多个业务模块需要与同一个服务端进行通信时,如果每个模块都独立创建 Service 实例,不仅浪费资源,还会增加进程管理的复杂度。Binder 线程池的核心作用在于统一管理这些请求,将不同业务模块的 Binder 调用统一转发到远程 Service 执行,从而避免重复创建 Service。
大致流程如下:
- 各业务模块定义自己的 AIDL 接口并实现具体逻辑,确保模块间无耦合。
- 向服务端注册唯一标识及对应的 Binder 对象。
- 服务端提供一个统一的
queryBinder接口,根据标识返回相应的 Binder 对象。 - 客户端获取 Binder 后直接进行远程方法调用。

下面我们通过代码模拟这一过程。
接口定义
首先创建两个 AIDL 接口来模拟不同的业务需求,例如安全中心和计算服务。
ISecurityCenter.aidl
// ISecurityCenter.aidl
package com.breezehan.ipc.binderpool;
interface ISecurityCenter {
String encrypt(String content);
String decrypt(String password);
}
ICompute.aidl
// ICompute.aidl
package com.breezehan.ipc.binderpool;
interface ICompute {
int add(int a, int b);
}
服务端实现
接下来实现上述接口。这里注意,AIDL 生成的 Stub 类通常用于转换接口和 Binder 对象。
public class SecurityCenterImpl 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 ComputeImpl extends ICompute.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
}
连接池代理
我们需要一个代理或工厂接口,根据标识返回对应的 Binder。这是连接池的关键入口。
IBinderPool.aidl
// IBinderPool.aidl
package com.breezehan.ipc.binderpool;
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
在连接池中实现该接口,根据传入的标识分发不同的 Binder 实例。
static class BinderPoolImpl extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case BINDER_COMPUTE:
binder = new ComputeImpl();
break;
case BINDER_SECURITY_CENTER:
binder = new SecurityCenterImpl();
break;
}
return binder;
}
}
Service 绑定
Service 本身逻辑很简单,主要职责是暴露 BinderPool 接口。
package com.breezehan.ipc.binderpool;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class BinderPoolService extends Service {
private static final String TAG = "BinderPoolService";
private IBinder binderPool = new BinderPool.BinderPoolImpl();
public BinderPoolService() {}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return binderPool;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
连接池管理
这部分是核心,负责处理 Service 的连接、单例模式以及 Binder 死亡代理问题。
public class BinderPool {
private static final String TAG = "BinderPool";
public static final int BINDER_NONE = -1;
public static final int BINDER_COMPUTE = 0;
public static final int BINDER_SECURITY_CENTER = 1;
private static volatile BinderPool sInstance;
private final Context mContext;
// 等待 Service 连接完成的同步工具
private CountDownLatch mConnectBinderPoolCountDownLatch;
private IBinderPool mBinderPool;
public BinderPool(Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}
private void connectBinderPoolService() {
mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext, BinderPoolService.class);
mContext.bindService(service, mServiceConnection, Context.BIND_AUTO_CREATE);
try {
mConnectBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static BinderPool getInstance(Context context) {
if (sInstance == null) {
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
mBinderPool.asBinder().linkToDeath(mBinderDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
mConnectBinderPoolCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 注意:此回调在服务端崩溃时触发,但无法保证 Binder 状态
}
};
private IBinder.DeathRecipient mBinderDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "binderDied: ");
mBinderPool.asBinder().unlinkToDeath(mBinderDeathRecipient, 0);
mBinderPool = null;
// 重连逻辑
connectBinderPoolService();
}
};
public IBinder queryBinder(int bindCode) {
IBinder binder = null;
try {
binder = mBinderPool.queryBinder(bindCode);
} catch (RemoteException e) {
e.printStackTrace();
}
return binder;
}
static class BinderPoolImpl extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case BINDER_COMPUTE:
binder = new ComputeImpl();
break;
case BINDER_SECURITY_CENTER:
binder = new SecurityCenterImpl();
break;
}
return binder;
}
}
}
客户端使用
在 Activity 中模拟调用。这里演示了如何获取 Binder 并进行远程交互。
public class BinderPoolActivity extends AppCompatActivity {
private static final String TAG = "BinderPoolActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_binder_pool);
new Thread(() -> doWork()).start();
}
private void doWork() {
BinderPool pool = BinderPool.getInstance(BinderPoolActivity.this);
// 获取安全中心 Binder
IBinder securityBinder = pool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
ISecurityCenter iSecurityCenter = ISecurityCenter.Stub.asInterface(securityBinder);
Log.d(TAG, "visit ISecurityCenter");
String msg = "helloworld-安卓";
try {
String encrypt = iSecurityCenter.encrypt(msg);
Log.d(TAG, "encrypt:" + encrypt);
Log.d(TAG, "decrypt:" + iSecurityCenter.decrypt(encrypt));
} catch (RemoteException e) {
e.printStackTrace();
}
// 获取计算服务 Binder
IBinder computeBinder = pool.queryBinder(BinderPool.BINDER_COMPUTE);
ICompute iCompute = ICompute.Stub.asInterface(computeBinder);
try {
Log.d(TAG, "compute: " + iCompute.add(1, 2));
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
基本思想如上,如果需要支持更多 Binder,只需在 Switch 语句中添加对应分支即可,扩展性良好。
选择合适的 IPC 方式
每种 IPC 方式都有其优缺点和适用场景,开发者需根据实际需求权衡。
| 名称 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Bundle | 简单易用 | 只能传输 Bundle 支持的数据类型 | 四大组件间的进程间通信 |
| 文件共享 | 简单易用 | 不适合高并发,无法做到即时通信 | 无并发访问情形,交换简单数据 |
| AIDL | 功能强大,支持一对多并发,实时通信 | 使用稍复杂,需处理线程同步 | 一对多通信且有 RPC 需求 |
| Messenger | 支持一对多串行通信,实时通信 | 不支持高并发,不能很好处理 RPC | 低并发的一对多即时通信 |
| ContentProvider | 数据源访问方便,支持 CRUD | 受约束的 AIDL,主要用于数据共享 | 一对多的进程间数据共享 |
| Socket | 功能强大,网络传输字节流 | 实现细节繁琐,不支持直接 RPC | 网络数据交换 |
通过对比可以看出,对于需要频繁调用的远程服务,AIDL 配合 Binder 线程池是较为稳健的选择。
