Binder管家之Binder连接池
IPC进程间通信(四)之AIDL中的AIDL由一个Service进行管理,若是创建10个AIDL业务模块是不是也要创建10个Service来进行管理,那100个呢?显然繁琐,怎么办么,用Binder连接池呀!
工作机制:
1.每个业务模块创建其AIDL接口并实现此接口生成具有唯一标识的Binder。
2.Binder连接池将每个业务模块的Binder统一转发给远程Service。
3.远程Service只需创建一个,并提供一个queryBinder接口,此接口根据业务模块的标识来返回相应的Binder给客户端,客户端即可进行远程方法调用。
一,创建业务模块AIDL
package com.example.binderpooltest;
//加法功能
interface IPlus {
int plus(int a,int b);
}
package com.example.binderpooltest;
//乘法功能
interface IMultiply {
int multiply(int a,int b);
}
创建一个连接池的AIDL接口queryBinder用于根据业务模块的标识来返回相应的Binder给请求者
package com.example.binderpooltest;
//连接池依binderCode查询Binder的接口
interface IBinderPool {
IBinder queryBinder(int binderCode);
}
二,创建子类继承自己的AIDL生成Binder
命名规则 xxImple
先make project 一下生成AIDL对应的 xxx.java文件
路径\app\build\generated\source\aidl\debug\包名\xxx.java
package com.example.binderpooltest;
import android.os.RemoteException;
/**
* 实现AIDL业务模块的Binder
* IPlus为自定义AIDL生成的java类
* public static abstract class Stub extends android.os.Binder implements com.example.binderpooltest.IPlus
* Stub继承自Binder所以IPlus.Stub即为Binder
* 所以IPlusImple也是一个Binder
*/
public class IPlusImple extends IPlus.Stub {
@Override
public int plus(int a, int b) throws RemoteException {
return a + b;
}
}
package com.example.binderpooltest;
import android.os.RemoteException;
public class IMultiplyImple extends IMultiply.Stub {
@Override
public int multiply(int a, int b) throws RemoteException {
return a * b;
}
}
三,创建BinderPool类作为连接池
知识点:
1.双锁实现单实例
2.共享锁CountDownLatch实现同步
3.IBinder.DeathRecipient实现服务断开重连
public class BinderPool {
private static final String TAG = "DEBUG-WCL: " + BinderPool.class.getSimpleName();
public static final int BINDER_CODE_ONE = 0;
public static final int BINDER_CODE_TWO = 1;
//自定义ADIL生成的IBinderPool.java类
private IBinderPool mBinderPool;
//第一锁volatile全局可见
private static volatile BinderPool sInstance;
private Context mContext;
// 同步机制
private CountDownLatch mCountDownLatch;
private BinderPool(Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}
// 单例
public static BinderPool getInstance(Context context) {
if (sInstance == null) {
//第二锁synchronized
synchronized (BinderPool.class) {
if (sInstance == null) {
sInstance = new BinderPool(context);
}
}
}
return sInstance;
}
// Binder的服务连接
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override public void onServiceConnected(ComponentName name, IBinder service) {
//以服务返回的IBinderPoolImple-Binder生成IBinderPool对象
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
mBinderPool.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
e.printStackTrace();
}
//设置次数减一,此时为零,下一个开始连接
mCountDownLatch.countDown();
}
@Override public void onServiceDisconnected(ComponentName name) {
}
};
// 绑定服务池
private synchronized void connectBinderPoolService() {
//排队连接,设置调用一次countDown()后,前一个连接断开,后一个开始连接
mCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext, BinderService.class);
mContext.bindService(service, mBinderPoolConnection, Context.BIND_AUTO_CREATE);
try {
//其余等待
mCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 失效重联机制, 当Binder死亡时, 重新连接
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override public void binderDied() {
Log.d(TAG, "Binder失效");
mBinderPool.asBinder().unlinkToDeath(mDeathRecipient, 0);
mBinderPool = null;
connectBinderPoolService();
}
};
/**
* 用于被客户端调用,请求Binder ,最终为向服务端请求
* 此时的mBinderPool为链接服务时从服务返回的IBinderPoolImple-Binder生成的IBinderPool接口
* 即可调用接口方法queryBinder(binderCode)即回掉到IBinderPoolImple.queryBinder(int binderCode)
* @param binderCode binder代码
* @return Binder
*/
public IBinder queryForBinder(int binderCode) {
IBinder binder = null;
try {
if (mBinderPool != null) {
binder = mBinderPool.queryBinder(binderCode);
}
} catch (RemoteException e) {
e.printStackTrace();
}
return binder;
}
/**
* 用于被服务端调用,运行与服务端,当客户端向BinderPool发起Binder请求,BinderPool向服务请求,返回Binder给客户端
* public static abstract class Stub extends android.os.Binder implements com.example.binderpooltest.IBinderPool
* IBinderPool.Stub实现了AIDL接口IBinderPool
* IBinderPoolImple继承IBinderPool.Stub,所以IBinderPoolImple重写了AIDL接口方法,若其他地方调用
* IBinderPool.queryBinder(binderCode)即会回调到此方法
*/
public static class IBinderPoolImple extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder iBinder = null;
switch (binderCode) {
case BINDER_CODE_ONE:
iBinder = new IPlusImple();
break;
case BINDER_CODE_TWO:
iBinder = new IMultiplyImple();
break;
}
return iBinder;
}
}
}
四,创建服务用于管理BinderPool发送过来的Binder
public class BinderService extends Service {
public BinderService() {
}
@Override
public void onCreate() {
super.onCreate();
}
//调用BinderPool中的,AIDL查询接口queryBinder的实现类,其中实现了依binderCode返回Binder的方法
//将此IBinder返回给BinderPool
private IBinder mBinder = new BinderPool.IBinderPoolImple();
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
五,前台客户端实现
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
//请求Binder的唯一标识
public static final int METHOD_CODE_ONE = 1;
public static final int METHOD_CODE_TWO = 2;
private Context mContext;
private BinderPool mBinderPool;
//请求并希望返回的IBinder
private IBinder mPlusBinder;
private IBinder mMultuplyBinder;
//以返回的IBinder创建的接口
private IPlus mIPlus;
private IMultiply mIMultiply;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = getApplicationContext();
new Thread(new doWork()).start();
}
private class doWork implements Runnable {
public doWork() {
super();
}
@Override
public void run() {
int a = 2;
int b = 5;
Log.d(TAG, "doWork: 1");
//创建BinderPool单实例
mBinderPool = BinderPool.getInstance(mContext);
Log.d(TAG, "doWork: 2");
try {
//请求的IBinder
mPlusBinder = mBinderPool.queryForBinder(METHOD_CODE_ONE);
Log.d(TAG, "doWork: 3");
//以返回的IBinder创建接口
mIPlus = IPlusImple.asInterface(mPlusBinder);
//调用远程方法
int result1 = mIPlus.plus(a, b);
mMultuplyBinder = mBinderPool.queryForBinder(METHOD_CODE_TWO);
mIMultiply = IMultiplyImple.asInterface(mMultuplyBinder);
int result2 = mIMultiply.multiply(a, b);
Toast.makeText(mContext, "a + b = " + result1 + "/n" +
"a × b = " + result2, Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}