内容参考自《Android开发艺术探索》
Binder连接池
- 工作机制:每个业务模块创建自己的AIDL接口并实现此接口,这个时候不同业务模块之间时不能有耦合的,所有实现细节都要单独开来,然后向服务端提供自己的唯一标识和其对应的Binder对象。
- Binder连接池的主要作用就是将每个业务模块的Binder请求统一转发到远程Service中去执行,从而避免了重复创建Service的过程,极大提高了AIDL的开发效率。
一、 Binder连接池的创建
实现Binder连接池的步骤
- 创建ADIL
- 实现各AIDL接口
- 服务端实现
- 连接池的实现
- 客户端的实现
- 在AndroidManifest.xml中注册服务
创建ADIL
// ISecurityCenter.aidl
interface ISecurityCenter {
String encrypt(String content);
String decrypt(String password);
}
// ICompute.aidl
interface ICompute {
int add(int a, int b);
}
// IBinderPool.aidl
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
- 实现各AIDL接口
// SecurityCenterImpl.java
public class SecurityCenterImpl extends ISecurityCenter.Stub {
private static final char SECRET_CODE = '^';
@Override
public String encrypt(String content) throws RemoteException {
char[] charArr = content.toCharArray();
for (int i = 0; i < charArr.length ; i++) {
charArr[i] ^= '^';
}
return new String(charArr);
}
@Override
public String decrypt(String password) throws RemoteException {
char[] charArr = password.toCharArray();
for (int i = 0; i < charArr.length ; i++) {
charArr[i] ^= '^';
}
return new String(charArr);
}
}
// ComputeImpl.java
public class ComputeImpl extends ICompute.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a+b;
}
}
// BinderPoolImpl.java
public class BinderPoolImpl extends IBinderPool.Stub {
public static final int BINDER_COMPUTE = 0;
public static final int BINDER_SECURITY_CENTER = 1;
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case BINDER_SECURITY_CENTER:
binder = new SecurityCenterImpl();
break;
case BINDER_COMPUTE:
binder = new ComputeImpl();
break;
default:
break;
}
return binder;
}
}
- 服务端实现
// BinderPoolService.java
public class BinderPoolService extends Service {
private Binder mBinderPoolImpl = new BinderPoolImpl();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinderPoolImpl;
}
}
- 连接池的实现
// BinderPool.java
public class BinderPool {
private static final String TAG = "BinderPool";
private Context mContext;
private IBinderPool mBinderPoolImpl;
private static volatile BinderPool sInstance;
private CountDownLatch mConnectBinderPoolCountDownLatch;
private BinderPool(Context context) {
mContext = context;
connectBinderPoolService();
}
public static BinderPool getInstance(Context context){
if (sInstance == null) {
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
private synchronized void connectBinderPoolService() {
mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
Intent intent = new Intent(mContext, BinderPoolService.class);
mContext.bindService(intent, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
try {
// 当前线程进入等待,直到主线程onServiceConnected执行完毕,则该线程唤醒
mConnectBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public IBinder queryBinder(int binderCode) {
IBinder binder = null;
try {
if (mBinderPoolImpl != null) {
binder = mBinderPoolImpl.queryBinder(binderCode);
}
} catch (RemoteException e) {
e.printStackTrace();
}
return binder;
}
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPoolImpl = IBinderPool.Stub.asInterface(service);
try {
mBinderPoolImpl.asBinder().linkToDeath(mBinderPoolDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
// 计数减1,当计数为0时唤醒被它阻塞的线程
mConnectBinderPoolCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.d(TAG, "binderDied: ");
mBinderPoolImpl.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
mBinderPoolImpl = null;
connectBinderPoolService();
}
};
}
- 客户端实现
// MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ISecurityCenter mSecurityCenter;
private ICompute mCompute;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
doWork();
}
}).start();
}
private void doWork() {
Log.d(TAG, "this: " + this);
Log.d(TAG, "MainActivity.this: " + MainActivity.this);
BinderPool binderPool = BinderPool.getInstance(MainActivity.this);
IBinder securityBinder = binderPool.queryBinder(BinderPoolImpl.BINDER_SECURITY_CENTER);
mSecurityCenter = SecurityCenterImpl.asInterface(securityBinder);
Log.d(TAG, "visit ISecurityCenter");
String msg = "helloworld-安卓";
Log.d(TAG, "content: " + msg);
try {
String password = mSecurityCenter.encrypt(msg);
Log.d(TAG, "encrypt: " + password);
Log.d(TAG, "decrypt: " + mSecurityCenter.decrypt(password));
} catch (RemoteException e) {
e.printStackTrace();
}
Log.d(TAG, "visit ICompute");
IBinder computeBinder = binderPool.queryBinder(BinderPoolImpl.BINDER_COMPUTE);
mCompute = ComputeImpl.asInterface(computeBinder);
try {
Log.d(TAG, "3+5 = " + mCompute.add(3, 5));
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
- 在AndroidManifest.xml中注册服务
<service android:name=".BinderPoolService"
android:process=":remote"/>
二、 Binder连接池的工作流程
- 这个过程好比于你(
Client
)打电话给10086(Service
),然后转接到人工服务,此时某位客服(mBinderPoolImpl
)接了你的电话,你跟客服说宽带对的但就是连不上,然后客服根据你的情况(mBinderPoolImpl.queryBinder()
RPC)把线路转接给了宽带技术客服(mClientNeededBinder
),后来你让宽带技术客服检查和重置宽带的连接状态(mNeededBinder.xxxMethod()
RPC),顺利的解决了问题。