----------------------Android开发艺术探索学习之Binder连接池----------------------
通常情况下,在使用AIDL时,一个Service需要创建一个AIDL接口,在Service中创建一个类集成AIDL接口中的Stub并实现抽象方法,在onBind中返回该类实例,然后在Client中绑定服务,建立连接后可以访问Service中方法,即在一个Service中只能返回一个业务调用的Binder。
当多个业务模块都需要使用AIDL时(如50个,100个),如果创建多个Service会消耗大量的系统资源,使应用重量级,为了减少Service的数量,可以将多有的AIDL 放在一个Service中去管理。
具体是:每个业务模块创建自己的AIDL接口并实现该接口,向服务提供自己唯一的Binder对象,对于Service端,只提供一个Service,Service提供一个queryBinder的接口,这个接口可以根据具体的业务模块返回相应的Binder对象给客户端。
Binder连接池的主要作用是统一各个业务模块的Binder并统一转发到远程Service中去执行,避免重复创建Service.
具体使用过程:
服务端:服务端实现各个模块的AIDL接口和Binder
import android.os.RemoteException;
// 这是计算模块的Binder实现
public class ComputeImpl extends ICompute.Stub {
@Override
public int add(int a, int b) throws RemoteException {
return a + b;
}
}
import android.os.RemoteException;
// 这是加密模块的Binder实现
public class SecurityCenterImpl extends ISecurityCenter.Stub {
private static final char SECRET_CODE = '^';
@Override
public String decrypt(String password) throws RemoteException {
return encrypt(password);
}
@Override
public String encrypt(String content) throws RemoteException {
char[] chars = content.toCharArray();
for (int i = 0; i < chars.length; i++) {
chars[i] ^= SECRET_CODE;
}
return new String(chars);
}
}
import android.os.IBinder;
import android.os.RemoteException;
// 这是BinderPool的Binder实现
public class BinderPoolImp extends IBinderPool.Stub {
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode) {
case 1: {
binder = new SecurityCenterImpl();
break;
}
case 2: {
binder = new ComputeImpl();
break;
}
default:
break;
}
return binder;
}
}
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
public class BinderPoolService extends Service {
private static final String TAG = "BinderPoolService";
private Binder binder = new BinderPoolImp();
@Override
public void onCreate() {
super.onCreate();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
这个Service的实现,在onBind中返回BinderPoolImpl实例。
然后是客户端:
public class BinderPool {
private final static String TAG = "BinderPool";
private Context context;
private IBinderPool binderPool;
private static volatile BinderPool instance;
private BinderPool(Context context) {
this.context = context;
connectBinderPoolService();
}
public boolean isConnected() {
return binderPool == null ? false : true;
}
private synchronized void connectBinderPoolService() {
Intent intent = new Intent("com.raeyu.BINDER_POOL_SERVICE");
intent.setPackage("com.example.raeyu.binderpool");
context.bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binderPool = IBinderPool.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);
}
public static BinderPool getInstance(Context context) {
if(instance == null) {
synchronized (BinderPool.class) {
if(instance == null) {
instance = new BinderPool(context);
}
}
}
return instance;
}
public IBinder queryBinder(int binderCode) {
IBinder iBinder = null;
try {
iBinder = binderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
return iBinder;
}
}
客户端使用单例模式,具体使用:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binderService();
}
private void binderService() {
new Thread(new Runnable() {
@Override
public void run() {
BinderPool binderPool = BinderPool.getInstance(MainActivity.this);
try {
sleep(1000);
IBinder security = binderPool.queryBinder(1);
Log.i("BinderPool", "onCreate: == " + security);
// 可以使用binder调用客户端的方法
ISecurityCenter securityCenter = ISecurityCenter.Stub.asInterface(security);
if(securityCenter != null) {
Log.i("BinderPool", "securityCenter: " + securityCenter.encrypt("hello world"));
Log.i("BinderPool", "securityCenter: " + securityCenter.decrypt("ni hao"));
}
IBinder compute = binderPool.queryBinder(2);
ICompute computeBinder = ICompute.Stub.asInterface(compute);
if(computeBinder != null)
Log.i("BinderPool", "computeBinder: " + computeBinder.add(2, 3));
} catch (RemoteException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
输出结果:
这就是Binder连接池的使用!!!!!!!!!