前言
在前面关于AIDL的讲解中,基本是一个AIDL对应一个Service。具体实现是把AIDL的实现类放到Sevice里面了,如图
所以就会有很大的局限性,即一个Service只能对应一个AIDL,假如说有多个模块,每个模块都有AIDL需求,那么就需要写多个Service,很显然这是很笨的写法,而Binder连接池就可以比较优雅的实现一个Service对应多个AIDL的需求
1.总体思路介绍
首先要把Stub的实现类和Service抽离,不让Service和他们有直接关系。再就是在Service的onBind方法中返回Binder连接池。这样用户再从连接池中取出相应的IBinder再去操作。
2.具体实现
①创建两个AIDL文件,模拟多个模块使用AIDL的情况
// ICalculate.aidl
interface ICalculate {
int add(in int num1,in int num2);
}
// ISpeak.aidl
interface ISpeak {
void speak();
}
②创建他们的实现类(不在Service里面)
其实这个实现类还是运行在服务端的进程中
/**
* Created by didiwei on 2022/5/21
* desc: ISpeak.aidl的实现类,这个类之前是放在Service中的,但是因为引入了Binder连接池,所以要把它和Service分开
* 但其实这个实现类还是运行在服务端的进程中
*/
public class SpeakImpl extends ISpeak.Stub{
@Override
public void speak() throws RemoteException {
int pid = android.os.Process.myPid();
Log.v("ljh","这里是SpeakImpl里的speak方法,当前进程ID为:" + pid);
}
}
/**
* Created by didiwei on 2022/5/21
* desc: ICalculate.aidl的实现类,这个类之前是放在Service中的,但是因为引入了Binder连接池,所以要把它和Service分开
* 但其实这个实现类还是运行在服务端的进程中
*/
public class CalculateImpl extends ICalculate.Stub {
@Override
public int add(int num1, int num2) throws RemoteException {
int pid = android.os.Process.myPid();
Log.v("ljh","这里是CalculateImpl里的add方法,当前进程ID为:" + pid);
return num1 + num2;
}
}
③创建Binder连接池的AIDL接口
// IBinderPool.aidl
interface IBinderPool {
IBinder queryBinder(in int binderCode);
}
④创建BinderPool类,在里面实现IBinderPool
/**
* Created by didiwei on 2022/5/21
* desc: 里面有IBinderPool的实现类
*/
public class BinderPool {
public static final int BINDER_SPEAK = 0;
public static final int BINDER_CALCULATE = 1;
private Context mContext;
private IBinderPool mBinderPool;
private static volatile BinderPool mInstance;//单例
private CountDownLatch mCountDownLatch;//实现线程同步的
//连接Service的回调
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinderPool = IBinderPool.Stub.asInterface(service);
try {
mBinderPool.asBinder().linkToDeath(mDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
}
mCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
//实现Service的重连
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
mBinderPool.asBinder().unlinkToDeath(mDeathRecipient,0);
mBinderPool = null;
connectBinderPoolService();
}
};
private BinderPool(Context context){
this.mContext = context;
connectBinderPoolService();
}
public static BinderPool getInstance(Context context){
if(mInstance == null){
synchronized (BinderPool.class){
if(mInstance == null){
mInstance = new BinderPool(context);
}
}
}
return mInstance;
}
//连接服务端
private synchronized void connectBinderPoolService(){
mCountDownLatch = new CountDownLatch(1);
//连接Service
Intent service = new Intent(mContext,BinderPoolService.class);
mContext.bindService(service,mServiceConnection,Context.BIND_AUTO_CREATE);
try {
mCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//对外暴露的 queryBinder 方法
public IBinder queryBinder(int binderCode){
IBinder iBinder = null;
if(mBinderPool != null){
try {
iBinder = mBinderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
}
return iBinder;
}
//IBinderPool的实现类
public static class BinderPoolImpl extends IBinderPool.Stub{
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder iBinder = null;
switch (binderCode){
case BINDER_SPEAK:
iBinder = new SpeakImpl().asBinder();
break;
case BINDER_CALCULATE:
iBinder = new CalculateImpl().asBinder();
break;
default:
break;
}
return iBinder;
}
}
}
⑤创建BinderPoolService
/**
* Created by didiwei on 2022/5/21
* desc: 服务端,这个Service只需要返回BinderPool即可
*/
public class BinderPoolService extends Service {
private int pid = android.os.Process.myPid();
private Binder mBinderPool = new BinderPool.BinderPoolImpl();//注意这里用Binder接收
public BinderPoolService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.v("ljh","这里是Service里的onBind方法,当前进程ID为:" + pid);
return mBinderPool;
}
}
注意为Service另起进程
⑥客户端调用
public class MainActivity extends AppCompatActivity {
private ISpeak iSpeak;
private ICalculate iCalculate;
private int pid = android.os.Process.myPid();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Thread(new Runnable() {
@Override
public void run() {
startWork();
}
}).start();
}
private void startWork(){
Log.v("ljh","这里是客户端,当前进程为:" + pid);
BinderPool instance = BinderPool.getInstance(this);
IBinder iBinderSpeak = instance.queryBinder(BinderPool.BINDER_SPEAK);
iSpeak = ISpeak.Stub.asInterface(iBinderSpeak);
try {
iSpeak.speak();
} catch (RemoteException e) {
e.printStackTrace();
}
IBinder iBinderCalculate = instance.queryBinder(BinderPool.BINDER_CALCULATE);
iCalculate = ICalculate.Stub.asInterface(iBinderCalculate);
try {
iCalculate.add(1,2);
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
注意:这里要在新线程中去执行,因为在Binder连接池的实现,我们通过CountDownLatch将bindService这一异步操作转换成了同步操作,这就意味着它可能是耗时的,同时Binder方法的调用过程也可能是耗时的,因此不建议放在主线程中去执行。
效果
3.文章推荐和项目地址
项目地址:https://github.com/LJHnb666666/BinderPoolDemo