使用BinderPool管理AIDL
前言
平时我们用到AIDL
,一般的流程可能是这样:
-
定义AIDL接口
-
定义服务,在
onBind
方法中返回实现了AIDL接口的Stub
类的实例 -
调用
bindService
方法,在ServiceConnection
的onServiceConnected
回调中获取到Binder
对象 -
通过Binder对象调用接口中的方法
如果我们只是用到比较少的AIDL调用,那么上面的方法的确是可行的,但是,如果需要调用数量较多的AIDL,那么可以通过先访问一个BinderPool,然后再由BinderPool来查询相关的Binder服务,再将Binder服务返回。通过这种统一管理的方式,可以方便地管理AIDL。
下面详细介绍BinderPool具体的定义
定义IBinderPool
定义IBinderPool
,queryBinder
方法返回IBinder
对象
interface IBinderPool {
IBinder queryBinder(int queryCode);
}
定义BinderPool
将BinderPool
定义为单例模式
。通过getInstance
获取到BinderPool的实例,并在构造方法
中连接BinderPoolService
private static class BinderPoolHolder {
static final BinderPool INSTANCE = new BinderPool();
}
public static BinderPool getInstance(Context context) {
mContext = context.getApplicationContext();
return BinderPoolHolder.INSTANCE;
}
private BinderPool() {
connectBinderPoolService();
}
private synchronized void connectBinderPoolService() {
countDownLatch = new CountDownLatch(1);
Intent intent = new Intent(mContext, BinderPoolService.class);
mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
BinderPoolService
返回IBinderPool对象
public class BinderPoolService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new BinderPool.BinderPoolImpl();
}
}
BinderPoolImpl
实现IBinderPool
接口方法,queryBinder根据queryCode返回对应的Binder
static class BinderPoolImpl extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int queryCode) throws RemoteException {
IBinder binder = null;
switch (queryCode) {
case QUERY_CODE_BINDER_A:
binder = new BinderA();
break;
case QUERY_CODE_BINDER_B:
binder = new BinderB();
break;
default:
break;
}
return binder;
}
}
ServiceConnection
在onServiceConnected
返回Binder对象,并绑定DeathRecipient
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binderPool = IBinderPool.Stub.asInterface(service);
try {
binderPool.asBinder().linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
DeathRecipient
private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
binderPool.asBinder().unlinkToDeath(deathRecipient, 0);
binderPool = null;
connectBinderPoolService();
}
};
完整的BinderPool代码
public class BinderPool {
public static final int QUERY_CODE_BINDER_A = 1;
public static final int QUERY_CODE_BINDER_B = 2;
private static Context mContext;
private CountDownLatch countDownLatch;
private IBinderPool binderPool;
public static BinderPool getInstance(Context context) {
mContext = context.getApplicationContext();
return BinderPoolHolder.INSTANCE;
}
private BinderPool() {
connectBinderPoolService();
}
private synchronized void connectBinderPoolService() {
countDownLatch = new CountDownLatch(1);
Intent intent = new Intent(mContext, BinderPoolService.class);
mContext.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public IBinder queryBinder(int queryCode) {
IBinder binder = null;
if (binderPool != null) {
try {
binder = binderPool.queryBinder(queryCode);
} catch (RemoteException e) {
e.printStackTrace();
}
}
return binder;
}
private static class BinderPoolHolder {
static final BinderPool INSTANCE = new BinderPool();
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binderPool = IBinderPool.Stub.asInterface(service);
try {
binderPool.asBinder().linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
binderPool.asBinder().unlinkToDeath(deathRecipient, 0);
binderPool = null;
connectBinderPoolService();
}
};
static class BinderPoolImpl extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int queryCode) throws RemoteException {
IBinder binder = null;
switch (queryCode) {
case QUERY_CODE_BINDER_A:
binder = new BinderA();
break;
case QUERY_CODE_BINDER_B:
binder = new BinderB();
break;
default:
break;
}
return binder;
}
}
}
定义IBinderA及实现类
interface IBinderA {
int calc(int a,int b);
}
public class BinderA extends IBinderA.Stub {
@Override
public int calc(int a, int b) throws RemoteException {
return a + b;
}
}
定义IBinderB及实现类
interface IBinderB {
String getInfo(String info);
}
public class BinderB extends IBinderB.Stub {
@Override
public String getInfo(String info) throws RemoteException {
return info + "-handled";
}
}
客户端调用BinderPool
由于在连接BinderPoolService时,是通过调用CountDownLatch.await(),等待onServiceConnected的回调,因此如果直接在主线程调用BinderPool的方法,会导致主线程阻塞,发生ANR,因此需要放到子线程去处理。
new Thread(new Runnable() {
@Override
public void run() {
try {
IBinder binder = BinderPool.getInstance(getApplicationContext()).queryBinder(BinderPool.QUERY_CODE_BINDER_A);
final int calc = IBinderA.Stub.asInterface(binder).calc(1, 2);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "calc:" + calc, Toast.LENGTH_SHORT).show();
}
});
IBinder binderB = BinderPool.getInstance(getApplicationContext()).queryBinder(BinderPool.QUERY_CODE_BINDER_B);
final String info = IBinderB.Stub.asInterface(binderB).getInfo("hello");
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "info:" + info, Toast.LENGTH_SHORT).show();
}
});
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
总结
通过定义BinderPool来管理所有的AIDL连接,当需要新增AIDL时,只需要增加对应的AIDL接口及对应的实现Binder,然后在BinderPool的queryBinder增加对应的queryCode处理即可。