您的位置:首页 > 移动开发 > Android开发

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 方式

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  aidl android