demo下载地址,此demo由两个module来区分Service和Client
- AIDL流程:先创建一个Service和一个AIDL接口,接着创建一个类继承自AIDL接口中的Stub类并实现Stub 中的抽象方法,在Service的onBind方法中返回这个类的对象,然后客户端就可以绑定服务 端Service,建立连接后就可以访问远程服务端的方法了。
- 上述是典型的AIDL使用流程,假设业务需要100个模块需要使用AIDL进行通信,为了避免创建100个Service占用资源且项目变得重量级,将所有的AIDL用一个Service去管理是必要的,从而学习Binder连接池就有必要了。
- 整个工作机制是这样的:每个业务模块创建自己的AIDL接口并实现 此接口,这个时候不同业务模块之间是不能有耦合的,所有实现细节我们要单独开来,然 后向服务端提供自己的唯一标识和其对应的Binder对象;对于服务端来说,只需要一个 Service就可以了,服务端提供一个queryBinder接口,这个接口能够根据业务模块的特征来 返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进行远程 方法调用了。由此可见,Binder连接池的主要作用就是将每个业务模块的Binder请求统一 转发到远程Service中去执行,从而避免了重复创建Service的过程。
- 下面对Binder连接池进行一个小的例子
- 首先创建两个AIDL业务接口,根据AIDL原理,服务端和客户端都需要创建
// ISecurityCenter.aidl
package com.demo.aidlservice;
// Declare any non-default types here with import statements
interface ISecurityCenter {
String encrypt(String content);
String decrypt(String password);
}
// ICompute.aidl
package com.demo.aidlservice;
// Declare any non-default types here with import statements
interface ICompute {
int add(int a , int b);
}
然后创建IBinderPool.aidl提供查询具体Binder接口
// IBinderPool.aidl
package com.demo.aidlservice;
// Declare any non-default types here with import statements
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
然后在Service端去实现接口
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++) {
System.out.print("chars = " + chars[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;
}
}
public class BinderPoolImpl extends IBinderPool.Stub {
private static final String TAG = "Service BinderPoolImpl";
public BinderPoolImpl() {
super();
}
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
Log.e(TAG, "binderCode = " + binderCode);
IBinder binder = null;
switch (binderCode) {
case 0:
binder = new SecurityCenterImpl();
break;
case 1:
binder = new ComputeImpl();
break;
default:
break;
}
return binder;
}
}
- 最后服务端要做的就是创建Service然后在manifests配置Service,绑定Service的时候返回IBinderPool的实现,客户端通过queryBinder方法去区分具体的IBinder对象
public class BinderPoolService extends Service {
private static final String TAG = "BinderPoolService";
private Binder mBinderPool = new BinderPoolImpl();
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return mBinderPool;
}
}
- 接下来是Client的代码,客户端除了需要根据AIDL原理需要和服务端一样的AIDL接口意外,还需要BinderPool来queryBinder获取Service服务。
public class BinderPool {
private static final String TAG = "BinderPool";
private Context mContext;
private IBinderPool mBinderPool;
private static volatile BinderPool sInstance;
public BinderPool(Context context) {
this.mContext = context.getApplicationContext();
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() {
Intent service = new Intent();
service.setComponent(new ComponentName("com.demo.aidlservice", "com.demo.aidlservice.BinderPoolService"));
mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
}
public IBinder queryBinder(int binderCode) {
IBinder binder = null;
try {
if (mBinderPool != null) {
binder = mBinderPool.queryBinder(binderCode);
}
} catch (RemoteException e) {
e.printStackTrace();
}
return binder;
}
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();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.e(TAG, "binderDied");
mBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient, 0);
mBinderPool = null;
connectBinderPoolService();
}
};
}
然后在Client中MainActivity中调用,我这里写了两个按钮点击分别获取不同的服务
public class MainActivity extends AppCompatActivity {
private static final String TAG = "Client MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void enc(View view) {
new Thread() {
@Override
public void run() {
BinderPool iBinderPool = BinderPool.getInstance(MainActivity.this);
try {
IBinder securityBinder = iBinderPool.queryBinder(0);
ISecurityCenter securityCenter = ISecurityCenter.Stub.asInterface(securityBinder);
String enc = securityCenter.encrypt("abc");
Log.e(TAG, "enc = " + enc);
String dec = securityCenter.decrypt("123");
Log.e(TAG, "dec = " + dec);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}.start();
}
public void add(View view) {
new Thread() {
@Override
public void run() {
BinderPool binderPool = BinderPool.getInstance(MainActivity.this);
try {
IBinder iBinder = binderPool.queryBinder(1);
ICompute iCompute = ICompute.Stub.asInterface(iBinder);
int sum = iCompute.add(1, 2);
Log.e(TAG, "sum = " + sum);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}.start();
}
}
- 以上就是Binder连接池的用法,如果增加服务端AIDL业务需求,只需修改服务端的BinderPoolImpl和新增对应的AIDL接口就可以了,BinderPool能够极大地提高AIDL的开 发效率,并且可以避免大量的Service创建,因此,建议在AIDL开发工作中引入BinderPool 机制。