通常情况下,每个AIDL接口对应一个Service进行进程间通信,若有多个ADIL接口,也要创建多个Service,但Service是系统资源,无限制增加的话,会占用过多内存。下面就介绍下Binder连接池,以及怎样实现一个Service管理多个ADIL接口。
Binder连接池,是将各个业务模块的Binder请求统一转发到远程Service中去执行,可避免重复创建Sevice。
1 首先提供ISecurity、IPay两个接口,用于密码校验和支付
interface ISecurity {
String encode(String psw);
String decode(String psw);
}
interface IPay {
void buy();
}
2 SecurityImpl、PayImpl是两个接口的实现
public class SecurityImpl extends ISecurity.Stub {//Stub内部类,其实就是一个Binder类
private static final String TAG = "SecurityImpl lyl123";
@Override
public String encode(String psw) throws RemoteException {
Log.e(TAG, "encode, psw = " + psw);
char[] chars = psw.toCharArray();
for (int i = 0;i < chars.length; i++){
chars[i] ^= '^';
}
return new String(chars);
}
@Override
public String decode(String psw) throws RemoteException {
Log.e(TAG, "decode: psw = " + psw);
return encode(psw);
}
}
public class PayImpl extends IPay.Stub {//Stub内部类,其实就是一个Binder类
private static final String TAG = "PayImpl lyl123";
@Override
public void buy() throws RemoteException {
Log.e(TAG, "buy something");
}
}
3 提供一个AIDL接口IBinderPool,并提供一个获取Binder的方法
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
4. Binder连接池的实现
public class BinderPool {
private static final String TAG = "BinderPool lyl123";
public static final int BIND_PAY = 1;
public static final int BIND_SECURITY = 2;
private Context mContext;
private static volatile BinderPool instance;
private ServiceConnection conn;
private IBinderPool mBinderPool;
private CountDownLatch mCountDownLatch;//用于线程间同步
//for client
//1. lazy singleton mode
public static BinderPool getInstance(Context context){
if (null == instance){
synchronized (BinderPool.class) {
if (null == instance) {
instance = new BinderPool(context);
}
}
}
return instance;
}
private BinderPool(Context context){
mContext = context.getApplicationContext();
bindPoolService();
}
private synchronized void bindPoolService() {
Log.e(TAG, "bindPoolService");
if (null == conn) {
mCountDownLatch = new CountDownLatch(1);//1.定目标:把计数器初始化为1
Intent service = new Intent(mContext, BinderPoolService.class);
conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
Log.e(TAG, "mBinderPool = " + mBinderPool);
try {
Log.e(TAG, "为Binder对象设置死亡代理");
mBinderPool.asBinder().linkToDeath(mBinderDeathRecipient, 1);
} catch (RemoteException e) {
e.printStackTrace();
}
mCountDownLatch.countDown();//3. go!
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
mContext.bindService(service, conn, Context.BIND_AUTO_CREATE);
try {
mCountDownLatch.await();//2.准备:所有线程准备
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, "bind Pool Service!");
} else {
Log.e(TAG, "have bind Pool Service!");
}
}
//死亡代理
private IBinder.DeathRecipient mBinderDeathRecipient = new IBinder.DeathRecipient(){
@Override
public void binderDied() {
if (null == mBinderPool){
return;
}
//清除死亡代理标志
mBinderPool.asBinder().unlinkToDeath(mBinderDeathRecipient, 1);
mBinderPool = null;
conn = null;
bindPoolService();
}
};
//获取Binder
public IBinder queryBinder(int binderCode){
IBinder binder = null;
try {
if (null != mBinderPool){
binder = mBinderPool.queryBinder(binderCode);
}
} catch (RemoteException e) {
e.printStackTrace();
}
return binder;
}
//for server
public static class BinderPoolImpl extends IBinderPool.Stub {//Stub内部类,其实就是一个Binder类
BinderPoolImpl(){
super();
}
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
Binder binder = null;
switch (binderCode){
case BIND_PAY://大小写转换:Ctrl + Shift + U
binder = new PayImpl();//PayImpl继承了IPay.Stub, IPay.Stub继承了Binder
break;
case BIND_SECURITY:
binder = new SecurityImpl();
break;
}
return binder;
}
}
}
Binder连接池的静态内部类BinderPoolImpl,用于服务端,继承了IBinderPool.Stub,并实现了queryBinder方法,即通过不同的binerCode获取不同业务模块对应的Binder。
其余部分都用于客户端。通过单例模式获取BinderPool实例后,绑定服务,同时为服务设置死亡代理,同时提供queryBinder方法,用于调用服务端的queryBinder方法,获取Binder。
5. 服务端的实现
public class BinderPoolService extends Service {
private static final String TAG = "BinderPoolService lyl123";
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind");
return new BinderPool.BinderPoolImpl();
}
}
Binder连接池中第40行的mBinderPool,即为服务端onBind方法中返回的new BinderPool.BinderPoolImpl()
mBinderPool = IBinderPool.Stub.asInterface(service);
6. 客户端的实现
public class MainActivity extends Activity {
private static final String TAG = "MainActivity lyl123";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
work();
}
}).start();
}
private void work() {
Log.e(TAG, "work");
BinderPool binderPool = BinderPool.getInstance(MainActivity.this);
Log.e(TAG, "binderPool = " + binderPool);
IBinder binder = binderPool.queryBinder(BinderPool.BIND_SECURITY);//获取Binder后使用
//将服务端的Binder对象转换成客户端所需的AIDL类型的的对象
ISecurity iSecurity = SecurityImpl.asInterface(binder);//ISecurity.Stub.asInterface
Log.e(TAG, "binder = " + binder + ", iSecurity = " + iSecurity);
try {
String encode = iSecurity.encode("password");
String decode = iSecurity.decode(encode);
Log.e(TAG, "decode = " + decode);
} catch (RemoteException e) {
e.printStackTrace();
}
binder = binderPool.queryBinder(BinderPool.BIND_PAY);
IPay iPay = PayImpl.asInterface(binder);
Log.e(TAG, "binder = " + binder + ", iPay = " + iPay);
try {
iPay.buy();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
Binder连接池中,通过CountDownLatch将bindService这一异步操作转换成了同步操作,这就意味着它有可能是耗时的,同时Binder方法的调用也可能是耗时的,因此,在子线程中执行。
7. 清单文件
8. 参考
《Android开发艺术探索》
CountDownLatch的简单理解