背景是这样的,我们使用aidl时候,如果只有一个远程服务,如上篇介绍aidl的文章中的王者荣耀使用阿里支付宝支付,支付成功了就ok了
但现在王者荣耀是腾讯的,必须支持微信支付。实际上我们做一个产品涉及支付的时候,支付宝,微信支付都是标配。
再类似扩展开来,如果我们的产品涉及很多远程服务,那是否每个远程服务都要新建呢?显然得综合管理。
因此我们把所有的远程服务抽象出来,之前的对外暴露的具体的服务换为连接池服务。
我们首先建立这个连接池服务aidl文件
package yunnex.com.testalipay; interface IBinderPoolService { IBinder queryBinder(int binderId); }
根据该服务,客户端可以根据需求调度不同的服务,为简单起见,服务端设定binderId=1时,返回支付宝服务,binderId=2时,返回微信支付服务。
然后我们建立唯一对客户端的远程服务BinderPoolService
public class BinderPoolService extends Service { //连接池管理的aidl对象 private IAlipayService mAlipayService; private IWxService mWxService; private Binder mBinderPool = new IBinderPoolService.Stub() { @Override public IBinder queryBinder(int binderId) throws RemoteException { IBinder binder=null; switch (binderId) { case 1: if (mAlipayService == null) { mAlipayService = new AlipayServiceImpl(); } binder = (IBinder) mAlipayService; break; case 2: if (mWxService == null) { mWxService = new WxServiceImpl(); } binder = (IBinder) mWxService; break; } Log.e("binderPool", "server BinderPoolService queryBinder:" + binder); return binder; } }; @Override public IBinder onBind(Intent intent) { return mBinderPool; } }
两个支付接口实现类分别如下:
public class AlipayServiceImpl extends IAlipayService.Stub { private int mMoney; @Override public boolean payMoney(int money) throws RemoteException { mMoney = money; return money > 0; } @Override public Diamond getDiamond() throws RemoteException { return new Diamond(mMoney * 10); } }
public class WxServiceImpl extends IWxService.Stub { private int mMoney; @Override public boolean payMoney(int money) throws RemoteException { mMoney = money; return money > 0; } @Override public Diamond getDiamond() throws RemoteException { return new Diamond(mMoney * 10); } }
这样服务端就完成了。
客户端调用(记得拷贝生成的文件):
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
当绑定时,此时连接后的回调返回的就不再是具体的服务了,而是连接池服务。
ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mBinderPool = IBinderPoolService.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mBinderPool = null; } };
public void payWithPool(View view) { try { int bindCode = 2; IBinder binder = mBinderPool.queryBinder(bindCode); Log.e(TAG, "client payWithPool binder:" + binder); switch (bindCode) { case 1: //Caused by: java.lang.ClassCastException: //android.os.BinderProxy cannot be cast to //yunnex.com.testalipay.IAlipayService //((IAlipayService) binder).payMoney(108); IAlipayService alipayService = IAlipayService.Stub.asInterface(binder); Log.e(TAG, "client payWithPool Service:" + alipayService); int money = 102; boolean b = alipayService.payMoney(money); if (b) { Toast.makeText(MainActivity.this, "使用支付宝支付成功" + money + "元,得到钻石:" + alipayService.getDiamond().getNum() + "颗", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show(); } break; case 2: IWxService wxService = IWxService.Stub.asInterface(binder); Log.e(TAG, "client payWithPool Service:" + wxService); int money2 = 103; boolean b2 = wxService.payMoney(money2); if (b2) { Toast.makeText(MainActivity.this, "使用微信支付成功" + money2 + "元,得到钻石:" + wxService.getDiamond().getNum() + "颗", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "支付失败", Toast.LENGTH_SHORT).show(); } break; } } catch (RemoteException e) { e.printStackTrace(); } }
这样支付宝支付和微信支付就使用连接池完成了。
当后续再出现xxx支付时或者什么远程服务时,不需再为其提供一个service组件,只需配置好aidl文件,实现接口,在连接池中加入case分支即可。